package com.iwhalecloud.bss.kite.cucc.service.scene;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.iwhalecloud.bss.kite.cucc.client.api.inst.IProdInstService;
import com.iwhalecloud.bss.kite.cucc.client.dto.pay.ResaleOrderRequest;
import com.iwhalecloud.bss.kite.dataservice.cache.KiteAttrConfigCache;
import com.iwhalecloud.bss.kite.dataservice.entity.KiteAttrConfig;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.iwhalecloud.bss.kite.cart.client.api.cart.query.IQueryKiteShoppingCartService;
import com.iwhalecloud.bss.kite.client.api.reception.IServiceOfferService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneAdditionalOfferInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneOfferInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneProdInstService;
import com.iwhalecloud.bss.kite.client.api.scene.operate.IOperateSceneService;
import com.iwhalecloud.bss.kite.client.dto.DataResult;
import com.iwhalecloud.bss.kite.client.dto.scence.create.request.CreateBaseOfferSceneRequest;
import com.iwhalecloud.bss.kite.client.dto.scence.create.request.CreateGiftSceneRequest;
import com.iwhalecloud.bss.kite.client.dto.spec.in.ContractOfferDetailDTO;
import com.iwhalecloud.bss.kite.client.dto.spec.in.OfferRoleDetailDTO;
import com.iwhalecloud.bss.kite.client.enums.FifthGenerationType;
import com.iwhalecloud.bss.kite.client.vo.scene.ProdRoleModuleVO;
import com.iwhalecloud.bss.kite.client.vo.spec.ServiceOfferVO;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.context.CommonContext;
import com.iwhalecloud.bss.kite.common.executor.MultiThreaExecutorManager;
import com.iwhalecloud.bss.kite.common.executor.enums.ExecutorTypeEmun;
import com.iwhalecloud.bss.kite.common.executor.task.ExecuteTask;
import com.iwhalecloud.bss.kite.common.executor.vo.ExecuteResult;
import com.iwhalecloud.bss.kite.common.unicode.UnicodeOperTypeKite;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteObjectUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.account.ILocalAccountService;
import com.iwhalecloud.bss.kite.cucc.client.api.attr.IUnicomRegionService;
import com.iwhalecloud.bss.kite.cucc.client.api.customerOrderInformation.UserCenterClient;
import com.iwhalecloud.bss.kite.cucc.client.api.goods.IGoodsService;
import com.iwhalecloud.bss.kite.cucc.client.api.inf.IInfServiceBus;
import com.iwhalecloud.bss.kite.cucc.client.api.order.ICommonSevice;
import com.iwhalecloud.bss.kite.cucc.client.api.order.IOrderService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.ICuccSceneService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.IInitSceneOfferInstService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.IInstLoader;
import com.iwhalecloud.bss.kite.cucc.client.dto.account.QryCustAccountReq;
import com.iwhalecloud.bss.kite.cucc.client.dto.attr.UnicomRegion;
import com.iwhalecloud.bss.kite.cucc.client.dto.cust.CuccContextCustDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.customerOrderInformation.QryGrpMemberDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.customerOrderInformation.QryGrpMemberListByGrpReq;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.AttrDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.goods.GoodsDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.inf.InfServContextDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.order.OrderInfo;
import com.iwhalecloud.bss.kite.cucc.client.dto.order.OrderInfoListReq;
import com.iwhalecloud.bss.kite.cucc.client.dto.order.OrderInfoReq;
import com.iwhalecloud.bss.kite.cucc.client.dto.order.OrderListInfo;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAcceptStaffDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAccountDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosAttrDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosContractDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDeliveryDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDiscountDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosGoodsDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosGoodsFeeDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosOrderDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosProductDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosRequestDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosUserDTO;
import com.iwhalecloud.bss.kite.cucc.client.dto.webService.CustContractRsp;
import com.iwhalecloud.bss.kite.cucc.client.vo.scene.CuccOfferInitVO;
import com.iwhalecloud.bss.kite.cucc.common.constant.CuccServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.common.util.CommonUtil;
import com.iwhalecloud.bss.kite.cucc.common.util.DateUtils;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.CuccOfferKeyAttrCache;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.CuccOfferOriginalInfoCache;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.ExtOrderInfoCache;
import com.iwhalecloud.bss.kite.cucc.manager.inst.CuccKiteOfferInstAcct;
import com.iwhalecloud.bss.kite.cucc.service.attr.LocalQuerySeqHelper;
import com.iwhalecloud.bss.kite.cucc.service.goods.GoodsHelper;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.GetMemberUserInfoTask;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.GetMemberUserInfoTaskRh;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.GiftOfferInstReloadExecuteTask;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.MainOfferInstReloadExecuteTask;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.OfferInstRelInfoReloadExecuteTask;
import com.iwhalecloud.bss.kite.cucc.service.job.scene.OfferInstReloadExecuteTask;
import com.iwhalecloud.bss.kite.cucc.service.pos.handler.CuccPosServiceUtils;
import com.iwhalecloud.bss.kite.cucc.service.route.InfServParamUtils;
import com.iwhalecloud.bss.kite.cucc.service.route.InfServRouteFactory;
import com.iwhalecloud.bss.kite.cucc.service.rule.check.Impl.MenuLoadingRuleCompletionService;
import com.iwhalecloud.bss.kite.cucc.service.scene.loader.CuccInstLoaderFactory;
import com.iwhalecloud.bss.kite.cucc.service.scene.util.CuccSceneUtil;
import com.iwhalecloud.bss.kite.cucc.service.util.ProdCateUtil;
import com.iwhalecloud.bss.kite.cucc.spec.impl.transfer.GoodsInfoTransfer;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferDetailCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ProductCache;
import com.iwhalecloud.bss.kite.dataservice.entity.DcPublic;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.OfferDetail;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.dto.KiteAttrDTO;
import com.iwhalecloud.bss.kite.manager.dto.KiteInstRelDTO;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInstAcct;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInstContract;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.scene.service.operate.OperateChangeService;
import com.iwhalecloud.bss.kite.manager.transaction.KiteTransactional;
import com.iwhalecloud.bss.kite.manager.util.KiteTransactionUtils;
import com.iwhalecloud.bss.kite.service.scene.attr.OperateInstAttrService;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.base.staticdata.ServiceOfferConst;
import com.ztesoft.bss.common.bo.LoginInfo;
import com.ztesoft.bss.common.exception.BssException;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.bss.common.util.StringUtil;
import com.ztesoft.common.logger.api.ZLogger;
import com.ztesoft.common.logger.factory.ZLoggerFactory;

@Service
public class CuccSceneService implements ICuccSceneService {

    private static final ZLogger LOGGER = ZLoggerFactory.getLogger(CuccSceneService.class, KeyConsts.LOG_MODULE);

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOperateSceneInstService operateSceneInstService;

    @Autowired
    private IOperateSceneService operateSceneService;

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private ICommonSevice commonService;

    @Autowired
    private IOperateSceneProdInstService operateSceneProdInstService;

    @Autowired
    private IOperateSceneOfferInstService operateSceneOfferInstService;

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IServiceOfferService serviceOfferService;

    @Resource(name = "manager.operateChangeService")
    private OperateChangeService operateChangeService;

    @Autowired
    private OperateInstAttrService operateInstAttrService;

    @Autowired
    private ICommonSevice commonSevice;

    @Autowired
    private IInfServiceBus infServiceBus;

    @Autowired
    private IInitSceneOfferInstService initSceneOfferInstService;

    @Autowired
    private IOperateSceneAdditionalOfferInstService operateSceneAdditionalOfferInstService;

    @Autowired
    private ILocalAccountService localAccountService;

    @Autowired
    private IProdInstService prodInstService;

    @Resource
    private IUnicomRegionService unicomRegionService;

    @SuppressWarnings("deprecation")
    @Override
    public DataResult<String> getCartIdFromES() {
        String cartId = null;
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        Map<String, Object> extParams = loginInfo.getUserInfo().getExtParams();
        if (KiteMapUtils.isNotEmpty(extParams) && Objects.isNull(extParams.get("KITE_SCENEINST_CARTID"))) {

            Long staffId = ContextUtil.getUserId();

            // 获取购物车的分片键，调用ES进行查询，暂时先放在登录信息缓存中,方便场景加载的时候从购物车中获取数据需要通过分片键获取 ，后续改动
            IQueryKiteShoppingCartService queryKiteShoppingCartService = SpringUtil
                .getBean(IQueryKiteShoppingCartService.class);
            // 获取分片键 cartId
            Long cartIdd = queryKiteShoppingCartService.getShoppingCartIdByEs(staffId.toString()).getResultObject();

            if (!KiteObjectUtils.isEmpty(cartIdd)) {
                cartId = cartIdd.toString();
                extParams.put("KITE_SCENEINST_CARTID", cartIdd.toString());
                ContextUtil.setLoginInfo(loginInfo);
            }
        }
        else {
            cartId = (String) extParams.get("KITE_SCENEINST_CARTID");
        }
        return ErrorConsts.SUCCESS.getResult(cartId);
    }

    @Override
    @KiteTransactional
    public DataResult<String> createOrderOfferScene(CuccOfferInitVO offerVO) {
        String cartId = this.getCartIdFromES().getResultObject();

        String offerId = offerVO.getOfferId();
        String serviceOfferId = Optional.ofNullable(offerVO.getServiceOfferId())
            .orElse(ServiceOfferConsts.SERVICE_OFFER_ORDER);
        // serviceOfferId = "1012"; //资源核查
        List<String> offerIds = offerVO.getOfferIds();
        if (KiteListUtils.isNotEmpty(offerVO.getSingleOffers())) {
            offerIds = offerVO.getSingleOffers().stream().map(ContractOfferDetailDTO::getOfferId)
                .collect(Collectors.toList());
        } else {
            Map<String, Object> goodsInfo = CuccOfferOriginalInfoCache.get(offerId);
            List<Map<String, Object>> saleGoods = KiteMapUtils.getValue(goodsInfo, "saleGoods");
            offerIds = saleGoods.stream().map(map -> {
                return KiteMapUtils.getString(map, "goodsSku");
            }).collect(Collectors.toList());
        }
/*        if (KiteListUtils.isNotEmpty(offerIds)) {
            offerId = offerIds.get(0);
        }*/
        if (KiteListUtils.isNotEmpty(offerIds)) {
            if(offerIds.contains(offerVO.getSkuId())){
                offerId = offerVO.getSkuId();
            }else{
                offerId = offerIds.get(0);
            }

        }
        List<OfferRoleDetailDTO> offerRoleDetailList = offerVO.getOfferRoleDetail();

        if (StringUtils.isBlank(offerId)) {
            ErrorConsts.OFFER_NOT_FOUND.throwOut();
        }

        Offer offer = OfferCache.get(offerId);
        if (offer == null) {
            ErrorConsts.OFFER_NOT_FOUND.throwOut();
        }

        String sceneInstId = KiteStringUtils.EMPTY;
        //区分接口和前台
        CommonContext.setMoreAttrData(true);

        if (KeyConsts.OFFER_TYPE_15.equals(offer.getOfferType())) {

            CreateGiftSceneRequest sceneRequest = new CreateGiftSceneRequest();
            sceneRequest.setCustId(offerVO.getCustId());
            sceneRequest.setCustName(offerVO.getCustName());
            sceneRequest.setLanId(ContextUtil.getLandId());
            sceneRequest.setOfferId(offerId);
            sceneRequest.setRegionId(ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString());
            sceneRequest.setServiceOfferId(serviceOfferId);
            sceneRequest.setSessionId("-1");
            sceneRequest.setStaffId(ContextUtil.getUserId().toString());
            // 礼包
            sceneInstId = operateSceneService.createGiftSceneInst(sceneRequest).getResultObject();
            //更新主产品主商品的属性，根据传进来的属性
            if (KiteListUtils.isNotEmpty(offerVO.getSingleOffers())) {
                for (ContractOfferDetailDTO offerDetailDTO : offerVO.getSingleOffers()) {
                    updateInstPriceAttr(offerDetailDTO.getAttrs(), offerVO.getPrice(), offerId);
                    List<KiteOfferInst> giftOfferInsts = querySceneInstService.listGiftOfferInsts(sceneInstId);
                    List<String> instIds = Lists.newArrayList();
                    if (KiteListUtils.isNotEmpty(giftOfferInsts)) {
                        instIds.addAll(giftOfferInsts.stream().map(KiteOfferInst::getInstId).collect(Collectors.toList()));
                        // 找礼包下主套餐销售品实例
                        giftOfferInsts.forEach(giftOfferInst -> {
                            instIds.addAll(querySceneInstService
                                .listMainOfferInstsFromGiftOfferInst(offerVO.getCustId(),
                                    giftOfferInst.getInstId())
                                .stream().map(KiteOfferInst::getInstId).collect(Collectors.toList()));
                        });
                    }
                    for (String instId : instIds) {
                        this.updateInstAttr(sceneInstId, instId, offerDetailDTO.getAttrs());
                    };
                }
            }
        } else if (CoreDataOffer.OFF_0005_10.equals(offer.getOfferType())) {
            CreateBaseOfferSceneRequest request = new CreateBaseOfferSceneRequest();
            request.setCustId(offerVO.getCustId());
            request.setCustName(offerVO.getCustName());
            request.setLanId(ContextUtil.getLandId());
            request.setOfferId(offerId);
            request.setRegionId(ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString());
            request.setServiceOfferId(serviceOfferId);
            request.setSessionId("-1");
            request.setStaffId(ContextUtil.getUserId().toString());
            // 基础销售品
            if (CollectionUtils.isEmpty(offerIds)) {
                sceneInstId = operateSceneService.createBaseOfferSceneInst(request).getResultObject();
            } else if (KiteListUtils.isNotEmpty(offerIds)) {
                request.setOfferIds(offerIds);
                sceneInstId = operateSceneService.createBaseOfferSceneInst(request).getResultObject();
            }
        } else if (CoreDataOffer.OFF_0005_13.equals(offer.getOfferType())) {
            // 销售商品
            if (KiteListUtils.isEmpty(offerIds)) {
                ErrorConsts.BUSI_CHECK_ERROR.getResult("基础商品不能为空");
            }
            offerRoleDetailList = checkAndGenOfferRoleDetail(offer, offerRoleDetailList, offerIds);
            sceneInstId = operateSceneService
                .createPromotionOfferSceneInst(serviceOfferId, offerId, offerVO.getCustId(),
                    offerVO.getCustName(), ContextUtil.getUserId().toString(),
                    ContextUtil.getLandId(), ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(),
                    "-1", offerRoleDetailList).getResultObject();

            //更新主产品主商品的属性，根据传进来的属性
            if (KiteListUtils.isNotEmpty(offerVO.getSingleOffers())) {
                for (ContractOfferDetailDTO offerDetailDTO : offerVO.getSingleOffers()) {
                    this.updateInstAttr(sceneInstId, querySceneInstService.listMainOfferInsts(sceneInstId).stream().filter(KiteOfferInst -> {
                        return KiteOfferInst.getOfferId().equals(offerDetailDTO.getOfferId());
                    }).findFirst().orElse(null).getOfferInstId(), offerDetailDTO.getAttrs());
                }
            }
        } else {
            offerRoleDetailList = checkAndGenOfferRoleDetail(offer, offerRoleDetailList, offerIds);
            List<String> detailIds = null;
            if (KiteListUtils.isNotEmpty(offerRoleDetailList)) {
                detailIds = offerRoleDetailList.get(0).getDetailIds();
            }
            sceneInstId = operateSceneService
                .createOfferSceneInst(serviceOfferId, offerId, offerVO.getCustId(),
                    offerVO.getCustName(), ContextUtil.getUserId().toString(),
                    ContextUtil.getLandId(), ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(),
                    "-1", detailIds).getResultObject();
            //更新主产品主商品的属性，根据传进来的属性
            if (KiteListUtils.isNotEmpty(offerVO.getSingleOffers())) {
                List<KiteAttrDTO> attrs;
                for (ContractOfferDetailDTO offerDetailDTO : offerVO.getSingleOffers()) {
                    attrs = offerDetailDTO.getAttrs();
                    updateInstPriceAttr(attrs, offerVO.getPrice(), offerId);
                    this.updateInstAttr(sceneInstId, querySceneInstService.listMainOfferInsts(sceneInstId).stream().filter(KiteOfferInst -> {
                        return KiteOfferInst.getOfferId().equals(offerDetailDTO.getOfferId());
                    }).findFirst().orElse(null).getOfferInstId(), attrs);
                }
            }
        }

        // 五大双线落地方产品，订购初始化，部分属性取值自原单，查询原单详情赋值
        this.initPlaceProductAttr(sceneInstId, offerVO);

        //保存受理的SPU，记录最新受理商品
        this.operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ACCEPT_GOODS_SPU, offerVO.getOfferId());
        this.operateSceneInstService.putExtParameter(sceneInstId, KeyConsts.IS_NEED_ANSY_MORE_ATTR, KeyConsts.ZERO);
        this.operateSceneAdditionalOfferInstService
            .handleAdditionOffer(sceneInstId, offerVO.getCustId(),
                ContextUtil.getUserId().toString(), offerVO.getFifthGenOffers(), FifthGenerationType.NEW);
        this.setSceneInstId(sceneInstId, offerVO.getCustId(), cartId, KiteStringUtils.equals(ServiceOfferConsts.SERVICE_OFFER_ORDER, serviceOfferId) ? UnicodeOperTypeKite.OPERTYPE_1001 : serviceOfferId);
        if (offerVO.getIsBatchAccept()) {
            operateSceneInstService.putExtParameter(sceneInstId, "nodeCode", "BatchInput");
            operateSceneInstService.putExtParameter(sceneInstId, "isBatchAccept", "T");
            operateSceneInstService.putExtParameter(sceneInstId, "saleGoodsCode", offerVO.getOfferId());
            operateSceneInstService.putExtParameter(sceneInstId, "singleOffers", offerVO.getSingleOffers());

        }

        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    private void setSceneInstId(String sceneInstId, String custId, String cartId, String operType) {
        KiteSceneInst kiteSceneInst = this.querySceneInstService.getSceneInst(sceneInstId, custId);
        if (KiteStringUtils.isNotEmpty(operType)) {
            kiteSceneInst.setOperType(operType);
        }
        kiteSceneInst.setCartId(cartId);
        this.operateSceneInstService.createSceneInst(kiteSceneInst);
    }

    /**
     * 校验入参是否正确，构造对象
     *
     * @param offer               销售品
     * @param offerRoleDetailList 销售品明细
     * @param offerIds            松融合主套餐列表
     */
    private List<OfferRoleDetailDTO> checkAndGenOfferRoleDetail(Offer offer,
                                                                List<OfferRoleDetailDTO> offerRoleDetailList, List<String> offerIds) {
        if (KiteListUtils.isEmpty(offerRoleDetailList)) {
            if (CoreDataOffer.OFF_0005_13.equals(offer.getOfferType()) && KiteListUtils.isNotEmpty(offerIds)) {
                offerRoleDetailList = new ArrayList<>();
                for (String offerId : offerIds) {
                    OfferRoleDetailDTO offerRoleDetail = new OfferRoleDetailDTO();
                    offerRoleDetail.setOfferId(offerId);
                    offerRoleDetailList.add(offerRoleDetail);
                }
            }
            return offerRoleDetailList;
        }

        if (CoreDataOffer.OFF_0005_13.equals(offer.getOfferType()) && KiteListUtils.isNotEmpty(offerIds)) {
            for (OfferRoleDetailDTO offerRoleDetail : offerRoleDetailList) {
                if (!offerIds.contains(offerRoleDetail.getOfferId())) {
                    ErrorConsts.ERROR_PARAM.throwOut();
                }
            }

            for (String offerId : offerIds) {
                if (offerRoleDetailList.stream()
                    .noneMatch(offerRoleDetailDTO -> offerRoleDetailDTO.getOfferId().equals(offerId))) {
                    OfferRoleDetailDTO offerRoleDetail = new OfferRoleDetailDTO();
                    offerRoleDetail.setOfferId(offerId);
                    offerRoleDetailList.add(offerRoleDetail);
                }
            }

        } else if (offerRoleDetailList.size() > 1 || !StringUtils
            .equals(offer.getOfferId(), offerRoleDetailList.get(0).getOfferId()) || KiteListUtils
            .isEmpty(offerRoleDetailList.get(0).getDetailIds())) {
            ErrorConsts.ERROR_PARAM.throwOut();
        }

        return offerRoleDetailList;

    }


    /**
     * 选择关键属性后，查询得到的价格，设置为价格属性的初始值
     * SDWAN商品编码：10003406
     */
    private static void updateInstPriceAttr(List<KiteAttrDTO> attrs, String price, String offerId) {
        if(KiteStringUtils.isNotBlank(price)) {
            String catId = Optional.ofNullable(OfferCache.get(offerId)).map(Offer::getCateId).orElse("");
            List<DcPublic> dcPublicList = DcPublicCache.getByPkey("2022022301", catId);
            if(CollectionUtils.isNotEmpty(dcPublicList)) {
                if(attrs == null) {
                    attrs = new ArrayList<>();
                }
                KiteAttrDTO priceAttr = new KiteAttrDTO();
                priceAttr.setFieldName(dcPublicList.get(0).getPcode());
                priceAttr.setValue(price);
                attrs.add(priceAttr);
            }
        }
    }

    @Override
    @KiteTransactional
    public DataResult<Map<String, Object>> createOfferScene(String serialNumber, List<QryGrpMemberDTO> memSerialNumbers, String prodId, String serviceOfferId, String custId,
        String custName, String staffId, String lanId, String regionId, String cartId, String userId) {
        StopWatch sw = new StopWatch("变更场景初始化");
        Map<String, Object> resultMap = new HashMap<>();

        Offer offer = OfferCache.get(prodId);
        if (Objects.isNull(offer)) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("商品不存在");
        }
        // 产品变更
        if (KiteStringUtils.isEmpty(serviceOfferId)) {
            serviceOfferId = ServiceOfferConst.service_offer_2826;
        }
        String offerType = offer.getOfferType();
        String provinceId = ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr();
        String staffCode = (String) ContextUtil.getLoginInfo().getUserInfo().getExtParams().get("account");

        /*Map<String, Object> orderInfo = orderService.getChangeOriginOrder(prodId, custId, serialNumber, provinceId, lanId, staffCode);
        KitePosDTO kitePosDTO = JSONObject
            .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);*/

        boolean hasMember = false;
        if (KiteStringUtils.isEqual(offerType, KeyConsts.OFFER_TYPE_15)) {
            // 如果是融合要拼接成员
            hasMember = true;
        }
        sw.start("变更场景初始化-获取全部变更单");
        Map<String, Object> kitePosDtoMap = this.getAllChangeOriginOrder(hasMember, memSerialNumbers, prodId, custId, serialNumber, provinceId, lanId, staffCode, userId).getResultObject();
        sw.stop();

        KitePosDTO kitePosDTO = (KitePosDTO) KiteMapUtils.getObject(kitePosDtoMap, "kitePosDTO");
        sw.start("变更场景初始化-创建场景");
        String sceneInstId = this.createOfferScene(serviceOfferId, null, LocalKeyConsts.ASK_SOURCE_USER, custId, custName, staffId, lanId, regionId, kitePosDTO).getResultObject();
        sw.stop();
        LOGGER.info(sw.prettyPrint());

        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("orderId", KiteMapUtils.getString(kitePosDtoMap, "orderId"));
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put(LocalKeyConsts.BUSI_CHANGE_SCENE, "T");
        sceneExtParams.put(LocalKeyConsts.BUSI_CHANGE_SCENE_ONE, "T");

        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);

        serviceOfferId = this.dealAddOrderExtParams(sceneInstId, serviceOfferId, Boolean.TRUE);
        this.setSceneInstId(sceneInstId, serviceOfferId, cartId, custId, "1008");

        resultMap.put("sceneInstId", sceneInstId);
        resultMap.put("kitePosDTO", kitePosDTO);

        return ErrorConsts.SUCCESS.getResult(resultMap);
    }

    /**
     * 设值上下文中的场景实例标识
     *
     * @param sceneInstId 场景实例标识
     */
    private void setSceneInstId(String sceneInstId, String serviceOfferId, String cartId, String custId, String operType) {
        KiteSceneInst kiteSceneInst = this.querySceneInstService.getSceneInst(sceneInstId, custId);
        if (KiteStringUtils.isNotEmpty(operType)) {
            kiteSceneInst.setOperType(operType);
        }
        kiteSceneInst.setServiceOfferId(serviceOfferId);
        kiteSceneInst.setCartId(cartId);
        this.operateSceneInstService.createSceneInst(kiteSceneInst);
    }

    /**
     * 设置追加订购扩展参数
     * @param sceneInstId
     * @param serviceOfferId
     * @param isGenSerialNumber 是否重新生成业务号码
     * @return
     */
    private String dealAddOrderExtParams(String sceneInstId, String serviceOfferId, boolean isGenSerialNumber) {
        // 思路：追加订购（2019）变更业务要求新生成号码,这里加场景标识,确保第一次初始化公共属性的时候生成新号码,后续每次刷页面不生成新号码。
        if (KiteStringUtils.isEqual(CuccServiceOfferConsts.SERVICE_OFFER_ADD_ORDER, serviceOfferId)) {
            serviceOfferId = ServiceOfferConst.service_offer_1;
            operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ADD_ORDE, "T");
            operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ADD_ORDE_RGE_NNUM, "T");
        }
        return serviceOfferId;
    }

    @Override
    public DataResult<String> createOfferSceneByOrderDetailInfo(String orderId, String serviceOfferId, String custId,
        String custName, String staffId, String lanId, String regionId, String operType) {

        Map<String, Object> orderInfo = orderService.getOrderDetail(orderId);
        KitePosDTO kitePosDTO = JSONObject
            .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);

        //this.initContext(kitePosDTO.getCustomer()); FIXME
        if (Objects.nonNull(kitePosDTO.getCustomer())) {
            String cust_id = kitePosDTO.getCustomer().getCbssId();
            kitePosDTO.getCustomer().setCustId(cust_id);
        }
        this.removeActivityGoods(kitePosDTO);

        String sceneInstId = this.createOfferScene(serviceOfferId, operType, LocalKeyConsts.ASK_SOURCE_ORDER,
            kitePosDTO.getCustomer().getCustId(), kitePosDTO.getCustomer().getName(), staffId,
            lanId, regionId, kitePosDTO).getResultObject();

        this.initSceneAttrValues(sceneInstId, operType, custId, staffId, kitePosDTO);

        // 回显订单概要信息
        this.saveOrderSummaryInfo(orderId, sceneInstId, kitePosDTO, null, null);
        // 回填A/Z端要求完成时间 公共属性替代
        this.replaceFinishTime(sceneInstId);

        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("orderId", orderId);
        //保存订单信息，用于封装订单信息模块
        sceneExtParams.put("orderInfoMap", orderInfo);
        //保存查到的用户信息节点，调任务完成接口时使用
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put("customer", kitePosDTO.getCustomer());

        String serviceOfferIdd = KiteMapUtils.getString((Map<String, Object>) orderInfo.get("ORDER"), "BIZ_TYPE");
        if (!KiteStringUtils.isEmpty(serviceOfferIdd)) {
            sceneExtParams.put("serviceOfferId", serviceOfferIdd);
        }

        String flowNodeId = KiteMapUtils.getString((Map<String, Object>) orderInfo.get("ORDER"), "FLOW_NODE_ID");
        if (!KiteStringUtils.isEmpty(flowNodeId)) {
            //sceneExtParams.put("nodeCode", flowNodeId.split("#")[0]);
            sceneExtParams.put("nodeCode", flowNodeId.replaceAll("#.*", "").replaceAll("_release_.*", ""));
        }
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);

        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    /**
     * 活动暂不支持，删除goods的活动节点
     *
     * @param kitePosDTO
     */
    private void removeActivityGoods(KitePosDTO kitePosDTO) {
        kitePosDTO.getGoods().removeIf(
            goods -> goods.getProducts().stream().anyMatch(prod -> KiteStringUtils.equals(prod.getType(), "discount")));
    }

    @Override
    public DataResult<Map<String, Object>> getOfferSceneDataByWorkOrder(String orderId, String flowId, String taskId,
        String serviceOfferId, String operType, String custId, String custName, String staffId, String lanId,
        String regionId, String orderSource) {
        // 获取工单信息
        InfServContextDTO context = InfServParamUtils.genGetWorkOrder(orderId, flowId, taskId, orderSource);
        Map<String, Object> workOrderInfo = InfServRouteFactory.getInstance().getWorkOrderInfo(context);

        Map<String, Object> worksheetData = (Map<String, Object>) workOrderInfo.get("worksheetData");
        JSONObject orderData = (JSONObject) workOrderInfo.get("orderData");

        // app甩单补录订单详情，若客户id为空，设置一个临时值，否则详情渲染报错
        Map<String, Object> customer = MapUtils.getMap(orderData, "customer");
        if(Objects.isNull(customer)) {
            customer = new HashMap<>();
            orderData.put("customer", customer);
        }
        if(KiteStringUtils.isEmpty(MapUtils.getString(customer, "cbssId"))) {
            customer.put("cbssId", LocalKeyConsts.TEMP_CBSS_ID);
        }

        KitePosDTO kitePosDTO = JSONObject.toJavaObject(orderData, KitePosDTO.class);
        this.setCustIdByCbssId(kitePosDTO);
        this.removeActivityGoods(kitePosDTO);
        String bizType = kitePosDTO.getOrder().getBizType();
        //支持多场景变更
        Map<String, String> resultMap = this.dealServiceOfferId(serviceOfferId, bizType, worksheetData, kitePosDTO);
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("nodeCode", this.getNodeCodeByWorkOrder(worksheetData));
        dataMap.put("serviceOfferId", KiteMapUtils.getString(resultMap, "serviceOfferId"));
        dataMap.put("upServiceOfferId", KiteMapUtils.getString(resultMap, "upServiceOfferId"));
        dataMap.put("serviceOfferIdList", KiteListUtils.strToList(",", bizType));
        dataMap.put("goodsNodeId", KiteMapUtils.getString(worksheetData, "goodsNodeId"));
        dataMap.put("worksheetData", worksheetData);
        dataMap.put("kitePosDTO", kitePosDTO);
        dataMap.put("orderData", orderData);
        return ErrorConsts.SUCCESS.getResult(dataMap);
    }

    @Override
    public DataResult<Map<String, Object>> getOfferSceneDataForChargePreCancel(String orderId, String flowId, String taskId, String serviceOfferId, String orderSource) {
        Map<String, Object> orderInfo = new HashMap<>();
        KitePosDTO kitePosDTO = null;

        // 1.查发起方工单详情获取发起方业务号码
        InfServContextDTO context = InfServParamUtils.genGetWorkOrder(orderId, flowId, taskId, orderSource);
        Map<String, Object> workOrderInfo = InfServRouteFactory.getInstance().getWorkOrderInfo(context);
        Map<String, Object> orderDetailMap = MapUtils.getMap(workOrderInfo, "orderData");
        List<Map<String, Object>> users = CommonUtil.getList(orderDetailMap, "users");
        if(KiteListUtils.isNotEmpty(users)) {
            Map<String, Object> user = users.get(0);
            String serialNumber = KiteMapUtils.getString(user, "serialNumber");
            if(KiteStringUtils.isNotEmpty(serialNumber)) {
                // 2.根据发起方业务号码，调用户详情接口（用户关系节点），查询收费方业务号码、收费方省市
                String provinceCode = KiteMapUtils.getString(user, "provinceCode");
                String cityCode = KiteMapUtils.getString(user, "cityCode");
                Map<String, String> chargeMap = prodInstService.queryChargeNumBySerialNumber(serialNumber, provinceCode, cityCode, "07");

                String serialNumberB = KiteMapUtils.getString(chargeMap, "serialNumberB");
                if(KiteStringUtils.isNotEmpty(serialNumberB)) {
                    // 3.根据收费方业务号码，查询收费方用户信息详情
                    String provinceCodeB = KiteMapUtils.getString(chargeMap, "provinceCodeB");
                    String cityCodeB = KiteMapUtils.getString(chargeMap, "cityCodeB");
                    provinceCodeB = KiteStringUtils.isNotEmpty(provinceCodeB) ? provinceCodeB : ContextUtil.getLoginInfo().getUserInfo().getPostProvinceNbr();
                    cityCodeB = KiteStringUtils.isNotEmpty(cityCodeB) ? cityCodeB : ContextUtil.getLandId();
                    String staffCode = (String) ContextUtil.getLoginInfo().getUserInfo().getExtParams().get("account");
                    orderInfo = orderService.getChangeOriginOrder(null, null, serialNumberB, provinceCodeB, cityCodeB, staffCode, null);

                    KitePosOrderDTO orderDTO = new KitePosOrderDTO();
                    Map<String, Object> order = MapUtils.getMap(orderDetailMap, "order");
                    orderDTO.setBizType(MapUtils.getString(order, "bizType"));

                    List<Map<String, Object>> goods = CommonUtil.getList(orderInfo, "goods");
                    if(KiteListUtils.isNotEmpty(goods)) {
                        List<String> doubleLineCateIds = ProdCateUtil.getDoubleLineCateId();
                        Map<String, Object> goodMap = goods.stream().filter(good -> doubleLineCateIds.contains(MapUtils.getString(good, "catagoryId"))).findAny().orElse(null);
                        String catagoryId = MapUtils.getString(goodMap, "catagoryId");
                        if(KiteStringUtils.isEmpty(catagoryId)) {
                            List<String> doubleLineOfferIds = ProdCateUtil.getDoubleLineOfferId();
                            goodMap = goods.stream().filter(good -> doubleLineOfferIds.contains(MapUtils.getString(good, "code"))).findAny().orElse(null);
                            catagoryId = Optional.ofNullable(OfferCache.get(MapUtils.getString(goodMap, "code"))).map(Offer::getCateId).orElse(null);
                        }

                        // 预销户-预销户原因-所有属性
                        String cateId = catagoryId;
                        List<KiteAttrConfig> preCancelAttrs = KiteAttrConfigCache.getAttrConfigTable(cateId, "1005", "128");
                        // 将发起的订单的预销户属性，赋值到消费方用户信息，以便初始化带出
                        List<Map<String, Object>> attrs = CommonUtil.getList(order, "attrs");
                        List<KitePosAttrDTO> attrDTOs = new ArrayList<>();
                        preCancelAttrs.forEach(kiteAttrConfig -> {
                            KitePosAttrDTO attrDTO = new KitePosAttrDTO();
                            Map<String, Object> attrMap = attrs.stream().filter(attr -> KiteStringUtils.isEqual(kiteAttrConfig.getAttrField(), MapUtils.getString(attr, "code"))).findAny().orElse(null);

                            attrDTO.setCode(MapUtils.getString(attrMap, "code"));
                            attrDTO.setEndDate(MapUtils.getString(attrMap, "endDate"));
                            attrDTO.setType(MapUtils.getString(attrMap, "type"));
                            attrDTO.setValue(MapUtils.getString(attrMap, "value"));
                            attrDTO.setStartDate(MapUtils.getString(attrMap, "startDate"));
                            attrDTOs.add(attrDTO);
                        });
                        orderDTO.setAttrs(attrDTOs);
                    }

                    Map<String, Object> customer = MapUtils.getMap(orderInfo, "customer");
                    String custId = MapUtils.getString(customer, "custId");
                    String cbssId = MapUtils.getString(customer, "cbssId");
                    if(!KiteStringUtils.isEqual(custId, cbssId) && KiteStringUtils.isNotEmpty(custId)) {
                        customer.put("cbssId", custId);
                    }

                    kitePosDTO = JSONObject.toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);
                    kitePosDTO.setOrder(orderDTO);
                }
            }
        }
        if(kitePosDTO == null) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("未查询到收费方用户信息");
        }

        Map<String, Object> worksheetData = (Map<String, Object>) workOrderInfo.get("worksheetData");

        this.removeActivityGoods(kitePosDTO);
        String bizType = kitePosDTO.getOrder().getBizType();
        //支持多场景变更
        Map<String, String> resultMap = this.dealServiceOfferId(serviceOfferId, bizType, worksheetData, kitePosDTO);
        Map<String, Object> dataMap = new HashMap<>();
        // 收费方预销户，原单是止租环节，收费单指定为OrderInput，按OrderInput配置页面流
        dataMap.put("nodeCode", "OrderInput");
        worksheetData.put("nodeCode", "OrderInput");
        // dataMap.put("nodeCode", this.getNodeCodeByWorkOrder(worksheetData));
        dataMap.put("serviceOfferId", KiteMapUtils.getString(resultMap, "serviceOfferId"));
        dataMap.put("upServiceOfferId", KiteMapUtils.getString(resultMap, "upServiceOfferId"));
        dataMap.put("serviceOfferIdList", KiteListUtils.strToList(",", bizType));
        dataMap.put("goodsNodeId", KiteMapUtils.getString(worksheetData, "goodsNodeId"));
        dataMap.put("worksheetData", worksheetData);
        dataMap.put("kitePosDTO", kitePosDTO);
        dataMap.put("orderData", orderInfo);
        return ErrorConsts.SUCCESS.getResult(dataMap);
    }

    @Override
    public DataResult<Map<String, Object>> getOfferSceneDataByOrderDetailInfo(String orderId, String serviceOfferId, String operType, String custId,
        String custName, String staffId, String lanId, String regionId) {
        Map<String, Object> orderInfo = orderService.getOrderDetail(orderId);
        KitePosDTO kitePosDTO = JSONObject
            .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);
        this.removeActivityGoods(kitePosDTO);
        String serviceOfferIdd = kitePosDTO.getOrder().getBizType();
        List<String> serviceOfferIdList = KiteListUtils.strToList(",", serviceOfferIdd);

        String upServiceOfferId = getUpServiceOfferId(serviceOfferIdList, kitePosDTO.getGoods());
        String flowNodeId = KiteMapUtils.getString((Map<String, Object>) orderInfo.get("ORDER"), "FLOW_NODE_ID");
        String nodeCode = "";
        if (KiteStringUtils.isNotEmpty(flowNodeId)) {
            nodeCode = flowNodeId.replaceAll("#.*", "").replaceAll("_release_.*", "");
        }
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("kitePosDTO", kitePosDTO);
        dataMap.put("orderInfo", orderInfo);
        dataMap.put("upServiceOfferId", upServiceOfferId);
        dataMap.put("serviceOfferId", serviceOfferIdd);
        dataMap.put("nodeCode", nodeCode);
        return ErrorConsts.SUCCESS.getResult(dataMap);
    }

    @Override
    @KiteTransactional
    public DataResult<Boolean> initModifySceneAttrValues(String sceneInstId, String operType, String custId, String staffId, String orderId,
                                                         String serviceOfferId, String upServiceOfferId, List<String> serviceOfferIdList,
                                                         Map<String, Object> worksheetData, KitePosDTO kitePosDTO, JSONObject orderData) {
        // 增加标识，当前是否为页面初始化渲染（如进入签订页面），忽略 Handler 的属性校验报错，否则会因为属性值校验不通过，导致页面渲染中断
        operateSceneInstService.putExtParameter(sceneInstId, "isInitPageRenderFlag", LocalKeyConsts.IFTRUE_T);
        Map<String, Object> loginExtParams = ContextUtil.getLoginInfo().getUserInfo().getExtParams();
        String preTaskCode = MapUtils.getString(loginExtParams,"preTaskCode");
        operateSceneInstService.putExtParameter(sceneInstId, "preTaskCode", preTaskCode);
        this.initSceneAttrValues(sceneInstId, operType, custId, staffId, kitePosDTO);

        serviceOfferId = this.dealAddOrderExtParams(sceneInstId, serviceOfferId, Boolean.FALSE);
        // 回显订单概要信息
        this.saveOrderSummaryInfo(orderId, sceneInstId, kitePosDTO, orderData, worksheetData);
        // 保存扩展信息
        this.saveSceneExtParams(sceneInstId, orderId, serviceOfferId, upServiceOfferId, serviceOfferIdList, worksheetData, kitePosDTO);
        // 初始化完毕，移除 页面初始化渲染 标识
        operateSceneInstService.removeExtParameter(sceneInstId, "isInitPageRenderFlag");
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    /**
     * app甩单订购初始化，回显甩单信息
     * @author zhang.song
     * @date 2021-08-19 17:32
     * @param sceneInstId
     * @param offerVO
     * @return com.iwhalecloud.bss.kite.client.dto.DataResult<java.lang.Boolean>
     */
    @Override
    @KiteTransactional
    public DataResult<Boolean> initRejectionSceneAttrValues(String sceneInstId, CuccOfferInitVO offerVO) {
        // 获取工单信息
        String orderId = offerVO.getOriginalOrderId();
        String flowId = offerVO.getFlowId();
        InfServContextDTO context = InfServParamUtils.genGetWorkOrder(orderId, flowId, null, null);
        Map<String, Object> workOrderInfo = InfServRouteFactory.getInstance().getWorkOrderInfo(context);
        JSONObject orderData = (JSONObject) workOrderInfo.get("orderData");
        KitePosDTO kitePosDTO = JSONObject.toJavaObject(orderData, KitePosDTO.class);

        // 判断是否变更产品，若另选了产品，则不回填产品、资费
        List<Map> goods = CommonUtil.getList(orderData, "goods");
        if (KiteListUtils.isNotEmpty(goods)) {
            String goodsSku = MapUtils.getString(goods.get(0), "saleGoodsCode");
            if (KiteStringUtils.isEmpty(goodsSku)) {
                goodsSku = goodsService.getPromotionOfferId(MapUtils.getString(goods.get(0), "code"));
            }
            boolean changeGoodFlag = KiteStringUtils.isEqual(offerVO.getOfferId(), goodsSku);

            if(changeGoodFlag) {
                // 选择产品与甩单产品相同，选择的关键属性覆盖甩单产品属性
                List<KitePosProductDTO> products = kitePosDTO.getGoods().get(0).getProducts();
                if(KiteListUtils.isNotEmpty(products) && KiteListUtils.isNotEmpty(offerVO.getSingleOffers())
                    && KiteListUtils.isNotEmpty(offerVO.getSingleOffers().get(0).getAttrs())) {
                    List<KitePosAttrDTO> attrs = products.get(0).getAttrs();
                    if(KiteListUtils.isNotEmpty(attrs)) {

                        offerVO.getSingleOffers().get(0).getAttrs().forEach(kiteAttrDTO -> {
                            KitePosAttrDTO attr = attrs.stream().filter(kitePosAttrDTO -> KiteStringUtils.isEqual(kitePosAttrDTO.getCode(), kiteAttrDTO.getFieldName())).findAny().orElse(null);
                            if(Objects.nonNull(attr)) {
                                attr.setValue(kiteAttrDTO.getValue());
                            }
                        });
                    }

                    // 处理资费中的标准月租属性，如果值为暂无价格，置为空
                    List<KitePosGoodsFeeDTO> fees = kitePosDTO.getGoods().get(0).getFees();
                    if(KiteListUtils.isNotEmpty(fees)) {
                        fees.forEach(kitePosGoodsFeeDTO -> {
                            if(KiteListUtils.isNotEmpty(kitePosGoodsFeeDTO.getAttrs())) {
                                kitePosGoodsFeeDTO.getAttrs().forEach(kitePosAttrDTO -> {
                                    if(LocalKeyConsts.STANDARD_MONTHLY_RENT.equals(kitePosAttrDTO.getCode()) && "暂无价格".equals(kitePosAttrDTO.getValue())) {
                                        kitePosAttrDTO.setValue("");
                                    }
                                });
                            }
                        });
                    }
                }
            } else {
                // 选择产品与甩单产品不同，不带出产品资费，将 kitePosDTO 产品、资费属性置空
                kitePosDTO.getGoods().get(0).setSaleGoodsCode(offerVO.getOfferId());
                if(KiteListUtils.isNotEmpty(offerVO.getSingleOffers())) {
                    kitePosDTO.getGoods().get(0).setCode(offerVO.getSingleOffers().get(0).getOfferId());
                } else {
                    List<OfferDetail> offerDetails = OfferDetailCache.get(offerVO.getOfferId());
                    if(KiteListUtils.isNotEmpty(offerDetails)) {
                        kitePosDTO.getGoods().get(0).setCode(offerDetails.get(0).getObjId());
                    }
                }

                kitePosDTO.getGoods().forEach(good -> {
                    good.setProducts(Lists.newArrayList());
                    good.setAttrs(Lists.newArrayList());
                    good.setFees(Lists.newArrayList());
                });
            }
        }

        operateSceneInstService.putExtParameter(sceneInstId, "renderOrderType", "orderRejection");
        operateSceneInstService.putExtParameter(sceneInstId, "rejectionOrderId", orderId);
        // 增加标识，当前是否为页面初始化渲染（如进入签订页面），忽略 Handler 的属性校验报错，否则会因为属性值校验不通过，导致页面渲染中断
        operateSceneInstService.putExtParameter(sceneInstId, "isInitPageRenderFlag", LocalKeyConsts.IFTRUE_T);

        String operType = LocalServiceOfferConsts.SERVICE_OFFER_ORDER;
        this.initSceneAttrValues(sceneInstId, operType, offerVO.getCustId(), ContextUtil.getUserId().toString(), kitePosDTO);

        // 保存扩展信息
        Map<String, Object> worksheetData = MapUtils.getMap(workOrderInfo, "worksheetData");
        this.saveSceneExtParams(sceneInstId, orderId, ServiceOfferConsts.SERVICE_OFFER_ORDER, null, null, worksheetData, kitePosDTO);
        // 初始化完毕，移除 页面初始化渲染 标识
        operateSceneInstService.removeExtParameter(sceneInstId, "isInitPageRenderFlag");
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    @Override
    @KiteTransactional
    public DataResult<Boolean> initDetailSceneAttrValues(String sceneInstId, String serviceOfferId, String operType,
        String cartId, String custId, String staffId, String orderId, String businessType,
        Map<String, Object> orderInfo, KitePosDTO kitePosDTO, String preTaskCode) {
        // 还原属性值
        this.initSceneAttrValues(sceneInstId, operType, custId, staffId, kitePosDTO);
        // 回显订单概要信息
        this.saveOrderSummaryInfo(orderId, sceneInstId, kitePosDTO, null, null);
        // 回填A/Z端要求完成时间 公共属性替代
        this.replaceFinishTime(sceneInstId);
        this.setSceneInstId(sceneInstId, serviceOfferId, cartId, custId, UnicodeOperTypeKite.OPERTYPE_1001);

        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("orderId", orderId);
        //保存订单信息，用于封装订单信息模块
        sceneExtParams.put("orderInfoMap", orderInfo);
        //保存查到的用户信息节点，调任务完成接口时使用
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put("customer", kitePosDTO.getCustomer());
        //回执信息
        sceneExtParams.put("outOrderId", orderId);
        //转单需要原单信息
        sceneExtParams.put("sourceOrderId", orderId);
        //记录页面URL的TYPE，用于区分业务类型
        sceneExtParams.put("businessType", businessType);
        // 记录环节标识（其中一种场景是批量受理）
        sceneExtParams.put("preTaskCode", preTaskCode);

        // 追单、加急、延期等，保存订单来源，提交时订单来源保持不变
        Map<String, Object> request = MapUtils.getMap(orderInfo, "REQUEST");
        KitePosRequestDTO requestDto = new KitePosRequestDTO(request);
        sceneExtParams.put("requestDto", requestDto);

        String serviceOfferIdd = kitePosDTO.getOrder().getBizType();
        List<String> serviceOfferIdList = KiteListUtils.strToList(",", serviceOfferIdd);

        String upServiceOfferId = getUpServiceOfferId(serviceOfferIdList, kitePosDTO.getGoods());
        if (KiteStringUtils.isNotEmpty(upServiceOfferId)) {
            sceneExtParams.put("BUSI_CHANGE_SERVICEOFFERID", serviceOfferIdList);

            if (LocalServiceOfferConsts.SERVICE_OFFER_FOLLOW.equals(serviceOfferId)) {
                sceneExtParams.put("upServiceOfferId", upServiceOfferId);
            }
        }
        if (!KiteStringUtils.isEmpty(serviceOfferIdd)) {
            sceneExtParams.put("serviceOfferId", serviceOfferIdd);
        }

        String flowNodeId = KiteMapUtils.getString((Map<String, Object>) orderInfo.get("ORDER"), "FLOW_NODE_ID");
        if (!KiteStringUtils.isEmpty(flowNodeId)) {
            //sceneExtParams.put("nodeCode", flowNodeId.split("#")[0]);
            sceneExtParams.put("nodeCode", flowNodeId.replaceAll("#.*", "").replaceAll("_release_.*", ""));
        }
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    /**
     * 保存场景扩展参数
     * @param sceneInstId
     * @param orderId
     * @param serviceOfferId
     * @param upServiceOfferId
     * @param serviceOfferIdList
     * @param worksheetData
     * @param kitePosDTO
     */
    private void saveSceneExtParams(String sceneInstId, String orderId, String serviceOfferId, String upServiceOfferId, List<String> serviceOfferIdList, Map<String, Object> worksheetData, KitePosDTO kitePosDTO) {
        // 场景扩展参数
        KiteSceneInst sceneInst = this.querySceneInstService.getSceneInst(sceneInstId);
        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        if (KiteStringUtils.isNotEmpty(upServiceOfferId)) {
            sceneExtParams.put("BUSI_CHANGE_SERVICEOFFERID", serviceOfferIdList);
            sceneInst.setServiceOfferId(serviceOfferId);
        }
        if (KiteStringUtils.isNotEmpty(kitePosDTO.getOrder().getBizType())) {
            sceneInst.setOperType(kitePosDTO.getOrder().getBizType());
        }
        else {
            sceneInst.setOperType(serviceOfferId);
        }
        operateSceneInstService.setSceneInst(sceneInst);
        // 场景初始化完成,移除特殊参数
        /*loginExtParams.remove("nodeCode");
        loginExtParams.remove("serviceOfferId");
        loginExtParams.remove("goodsNodeId");*/
        // 保存订单扩展信息，签订转单需要从中获取taskCode，taskName
        String nodeCode = this.getNodeCodeByWorkOrder(worksheetData);
        sceneExtParams.put("worksheetId", KiteMapUtils.getStrValue(worksheetData, "flowId"));
        sceneExtParams.put("nodeCode", nodeCode);
        sceneExtParams.put("serviceOfferId", serviceOfferId);
        sceneExtParams.put("orderId", MapUtils.getString(worksheetData, "orderId"));
        sceneExtParams.put("taskId", MapUtils.getString(worksheetData, "taskId"));
        sceneExtParams.put("taskCode", MapUtils.getString(worksheetData, "taskCode"));
        sceneExtParams.put("serialNumber", kitePosDTO.getUsers());
        sceneExtParams.put("customer", kitePosDTO.getCustomer());
        sceneExtParams.put("worksheetData", worksheetData);
        sceneExtParams.put("requestDto", kitePosDTO.getRequest());
        sceneExtParams.put("entry", "sceneTempl");
        sceneExtParams.put("outOrderId", orderId);
        sceneExtParams.put("isTransferOrderScene", "F");
        if (CuccSceneUtil.isTransferOrderSceneByWorkSheetInfo(orderId, kitePosDTO)) {
            sceneExtParams.put("isTransferOrderScene", "T");
        }
        // 资源核查甩单补录
        if (KiteStringUtils.isEqual(serviceOfferId, "1012") && KiteStringUtils.isEqual(nodeCode, "OrderAddRecord")) {
            sceneExtParams.put("renderOrderType", "orderRejection");
        }
        // 保存订单环节处理信息
        String businessData = MapUtils.getString(worksheetData, "orderData");
        if (!KiteStringUtils.isEmpty(businessData)) {
            Map<String, Object> orderDataMap = JSONObject.parseObject(businessData, Map.class);
            Map<String, Object> exceptionInfo = (Map<String, Object>) orderDataMap.get("exceptionInfo");
            sceneExtParams.put(LocalKeyConsts.SCENE_EXT_PARAM_EXCEPTION_INFO, exceptionInfo);
        }
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);
    }

    /**
     * 设置客户ID为CbssId
     */
    private void setCustIdByCbssId(KitePosDTO kitePosDTO) {
        if (Objects.nonNull(kitePosDTO.getCustomer())) {
            String cust_id = kitePosDTO.getCustomer().getCbssId();
            kitePosDTO.getCustomer().setCustId(cust_id);
        }
    }

    /**
     * 获取服务提供映射，获取多场景变更的所有服务提供以及对应的上级服务提供
     * @param serviceOfferId
     * @param bizType
     * @param worksheetData
     * @param kitePosDTO
     * @return
     */
    private Map<String, String> dealServiceOfferId(String serviceOfferId, String bizType, Map<String, Object> worksheetData, KitePosDTO kitePosDTO) {
        //先取映射，取不到直接把bizType作为serviceOfferId
        if (KiteStringUtils.isBlank(serviceOfferId)) {
            serviceOfferId = DcPublicCache.getPCode("20201130001", bizType);
        }
        //支持多场景变更
        List<String> serviceOfferIdList = KiteListUtils.strToList(",", bizType);

        String upServiceOfferId = getUpServiceOfferId(serviceOfferIdList, kitePosDTO.getGoods());
        if (KiteStringUtils.isBlank(serviceOfferId)) {
            if (KiteStringUtils.isEmpty(upServiceOfferId)) {
                serviceOfferId = bizType;
            }
            else {
                serviceOfferId = upServiceOfferId;
            }
        }

        if(KiteStringUtils.equals(serviceOfferId, "1")  && KiteStringUtils.equals("OrderSigned", KiteMapUtils.getString(worksheetData, "taskCode"))){
            if(KiteStringUtils.equals("1", KiteMapUtils.getString(worksheetData, "orderSource"))&&KiteStringUtils.equals(ProdCateUtil.getSingleCateId(ProdCateUtil.MV_CODE), KiteMapUtils.getString(worksheetData, "goodsNodeId"))){
                // MPLS-VPN  核差转定-订单签订
                serviceOfferId = LocalServiceOfferConsts.SERVICE_OFFER_TRANSFER_TO_ORDER;
            }
            // 二级研发跳转省份应用页面流 产品做核查转定-订单签订特殊处理
            String dcList = DcPublicCache.getCodea("20210805012", "SALE_KITE_SECDEV");
            if(dcList.contains(KiteMapUtils.getString(worksheetData, "goodsCode"))){
                serviceOfferId = LocalServiceOfferConsts.SERVICE_OFFER_TRANSFER_TO_ORDER;
            }
        }

        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("serviceOfferId", serviceOfferId);
        resultMap.put("upServiceOfferId", upServiceOfferId);

        return resultMap;
    }

    /**
     * 获取环节编码
     * @param worksheetData
     * @return
     */
    private String getNodeCodeByWorkOrder(Map<String, Object> worksheetData) {
        // 如果有异常，返回重提编码
        String exceptionType = (String) worksheetData.get("exceptionType");
        String nodeCodeStr = (String) worksheetData.get("nodeCode");
        if (!KiteStringUtils.isEmpty(exceptionType)) {
            //特殊处理 如果订单起租后被打回 重新进起租场景进行重提
            if(KiteStringUtils.isNotEmpty(nodeCodeStr) && KiteStringUtils.equalsAny(nodeCodeStr,"OrderStartRent")){
                return nodeCodeStr.split("#")[0];
            }
            if(KiteStringUtils.isNotEmpty(nodeCodeStr) && KiteStringUtils.equalsAny(nodeCodeStr,"OrderStopRent")){
                return nodeCodeStr.split("#")[0];
            }
            return "OrderResubmit";
        }

        if (!KiteStringUtils.isEmpty(nodeCodeStr)) {
            return nodeCodeStr.split("#")[0];
        }
        return "OrderInput";
    }

    @Override
    public void updateInstAttr(String sceneInstId, String offerInstId, List<KiteAttrDTO> attrs) {
        String custId = this.querySceneInstService.getSceneInst(sceneInstId).getCustId();
        if (!KiteListUtils.isEmpty(attrs)) {
            for (KiteAttrDTO attr : attrs) {
                operateSceneOfferInstService
                    .updateOfferInstAttr(sceneInstId, offerInstId, attr.getFieldName(), attr.getValue(),
                        attr.getValueDesc(), custId,
                        ContextUtil.getUserId().toString());
                //商品属性选择后对应的产品属性也一致
                List<KiteProdInst> prodInsts = querySceneInstService
                    .listProdInstsFromOfferInst(custId, offerInstId);
                prodInsts.forEach(kiteProdInst -> {
                    operateSceneProdInstService
                        .updateProdInstAttr(sceneInstId, kiteProdInst.getProdInstId(), attr.getFieldName(),
                            attr.getValue(), attr.getValueDesc(), custId,
                            ContextUtil.getUserId().toString(), null);
                });
            }
        }
    }

    @Override
    @KiteTransactional
    public DataResult<String> createOfferScene(String serviceOfferId, String operType, String askSource, String custId,
        String custName, String staffId, String lanId, String regionId, KitePosDTO kitePosDTO) {
        String sceneInstId = this.initModifyScene(serviceOfferId, operType, askSource, custId, custName, staffId, lanId, regionId, kitePosDTO).getResultObject();
        //如果是签订，才放到缓存中--都保存，订单中心会重新生成instanceId，保存也无影响 2020-09-19
        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    @Override
    @KiteTransactional
    public DataResult<String> initModifyScene(String serviceOfferId, String operType, String askSource, String custId,
        String custName, String staffId, String lanId, String regionId, KitePosDTO kitePosDTO) {
        // 追加订购使用服务提供1初始化场景
        boolean addOrder = false;
        if (KiteStringUtils.isEqual(CuccServiceOfferConsts.SERVICE_OFFER_ADD_ORDER, serviceOfferId)) {
            addOrder = true;
            serviceOfferId = ServiceOfferConst.service_offer_1;
        }
        List<KitePosGoodsDTO> offerInsts = kitePosDTO.getGoods();

        String promotionOfferId = null;
        String catagoryId = null;
        List<String> addRoleOfferIds = new ArrayList<>();
        List<String> singleOfferIds = new ArrayList<>();
        List<String> giftOfferIds = new ArrayList<>();
        List<String> totalOfferIds = new ArrayList<>();
        String giftCatagoryId = "";
        for (KitePosGoodsDTO offerInst : offerInsts) {
            String offerId = offerInst.getCode();
            totalOfferIds.add(offerId);
            if (GoodsHelper.isGift(offerId)) {
                giftOfferIds.add(offerId);
                giftCatagoryId = offerInst.getCatagoryId();
                continue;
            }
            promotionOfferId = offerInst.getSaleGoodsCode();
            if (!GoodsInfoTransfer.isAddRoleOffer(offerId, offerInst.getCatagoryId())) {
                singleOfferIds.add(offerId);
                catagoryId = offerInst.getCatagoryId();
            }
            else {
                addRoleOfferIds.add(offerId);
            }
        }
        if (KiteStringUtils.isNotEmpty(giftCatagoryId)) {
            catagoryId = giftCatagoryId;
        }
        List<OfferRoleDetailDTO> offerRoleDetailList = new ArrayList<>();
        for (String offerId : singleOfferIds) {
            OfferRoleDetailDTO offerRoleDetail = new OfferRoleDetailDTO();
            offerRoleDetail.setOfferId(offerId);
            offerRoleDetailList.add(offerRoleDetail);
        }

        //核查单可能从其它途径过来，SaleGoodsCode不一定有值
        //通过基础商品下的catagoryId去反查
        String sceneInstId = "";
        if (KiteStringUtils.isEmpty(promotionOfferId) && StringUtil.isNotEmpty(catagoryId)) {
            promotionOfferId = getPromotionOfferId(catagoryId, totalOfferIds);
        }

        for (KitePosGoodsDTO offerInst : offerInsts) {
            offerInst.setSaleGoodsCode(promotionOfferId);
            offerInst.setSaleGoodsName(Optional.ofNullable(OfferCache.get(promotionOfferId)).map(Offer::getOfferName).orElse(""));
        }
        //ServiceContext.setIsExecuteAfter(Boolean.FALSE);
        if (KiteListUtils.isNotEmpty(giftOfferIds)) {
            CreateGiftSceneRequest sceneRequest = new CreateGiftSceneRequest();
            sceneRequest.setCustId(custId);
            sceneRequest.setCustName(custName);
            sceneRequest.setLanId(lanId);
            sceneRequest.setOfferId(giftOfferIds.get(0));
            sceneRequest.setRegionId(ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString());
            sceneRequest.setServiceOfferId(serviceOfferId);
            sceneRequest.setSessionId("-1");
            sceneRequest.setStaffId(ContextUtil.getUserId().toString());

            // 礼包
            sceneInstId = operateSceneService.createGiftSceneInst(sceneRequest).getResultObject();
            // <goods.instanceId, user.serialNumber>
            Map<String, String> serialNumberMap = new HashMap<>();
            List<KitePosUserDTO> users = Optional.ofNullable(kitePosDTO.getUsers()).orElse(new ArrayList<>());
            users.forEach(kitePosUserDTO -> offerInsts.stream().filter(kitePosGoodsDTO -> KiteStringUtils
                .isEqual(kitePosGoodsDTO.getUserInstId(), kitePosUserDTO.getInstanceId())).findFirst()
                .map(KitePosGoodsDTO::getInstanceId)
                .ifPresent(goodInstId -> serialNumberMap.put(goodInstId, kitePosUserDTO.getSerialNumber())));
            operateSceneInstService.putExtParameter(sceneInstId, "serialNumberMap", serialNumberMap);
            operateSceneInstService.putExtParameter(sceneInstId, "instSerialNumberMap", new HashMap<>());
        }
        else {
            if (KiteListUtils.isNotEmpty(singleOfferIds)) {
                List<String> detailIds = null;
                if (KiteListUtils.isNotEmpty(offerRoleDetailList)) {
                    detailIds = offerRoleDetailList.get(0).getDetailIds();
                }
                sceneInstId = operateSceneService
                    .createOfferSceneInst(serviceOfferId, singleOfferIds.get(0), custId, custName,
                        ContextUtil.getUserId().toString(), lanId,
                        ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(),
                        String.valueOf(ContextUtil.getLoginInfo().getUserInfo().getExtParams().get("session_id")),
                        detailIds).getResultObject();

                //解决融合子单起租失败重提时,成员商品匹配userInstId为空问题。
                Map<String, String> serialNumberMap = new HashMap<>();
                List<KitePosUserDTO> users = Optional.ofNullable(kitePosDTO.getUsers()).orElse(new ArrayList<>());
                users.forEach(kitePosUserDTO -> offerInsts.stream().filter(kitePosGoodsDTO -> KiteStringUtils
                    .isEqual(kitePosGoodsDTO.getUserInstId(), kitePosUserDTO.getInstanceId())).findFirst()
                    .map(KitePosGoodsDTO::getInstanceId)
                    .ifPresent(goodInstId -> serialNumberMap.put(goodInstId, kitePosUserDTO.getSerialNumber())));
                operateSceneInstService.putExtParameter(sceneInstId, "serialNumberMap", serialNumberMap);
                operateSceneInstService.putExtParameter(sceneInstId, "instSerialNumberMap", new HashMap<>());
            }
            else {
                sceneInstId = operateSceneService
                    .createPromotionOfferSceneInst(serviceOfferId, promotionOfferId, custId, custName, staffId, lanId,
                        regionId, "-1", offerRoleDetailList).getResultObject();
            }
        }
        //KiteWebContext.addAndUpdateSceneInstId(sceneInstId);
        KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId);
        sceneInst.setAskSource(askSource);
        operateSceneInstService.setSceneInst(sceneInst);

        Map<String, Object> extParams = ContextUtil.getLoginInfo().getUserInfo().getExtParams();
        if (KiteMapUtils.isNotEmpty(extParams) && extParams.containsKey("nodeCode")) {
            this.operateSceneInstService.putExtParameter(sceneInstId, "initSource", "workOrder");
        }
        this.operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.BUSI_CHANGE_SCENE_ONE, "T");
        KitePosOrderDTO order = kitePosDTO.getOrder();
        if (Objects.nonNull(order)) {
            String bizType = Optional.ofNullable(order.getBizType()).orElse("");
            String upstreamOrderId = Optional.ofNullable(order.getUpstreamOrderId()).orElse("");
            this.operateSceneInstService.putExtParameter(sceneInstId, "bizType", bizType);
            this.operateSceneInstService.putExtParameter(sceneInstId, "upstreamOrderId", upstreamOrderId);
        }
        if (addOrder) {
            this.operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ADD_ORDE, "T");
        }
        this.operateSceneInstService.putExtParameter(sceneInstId, LocalKeyConsts.ACCEPT_GOODS_SPU, promotionOfferId);
        this.operateSceneInstService.putExtParameter(sceneInstId, "contract", kitePosDTO.getContract());
        // VIK公共属性初始化需要用户状态，开户时间
        this.operateSceneInstService.putExtParameter(sceneInstId, "userInfos", kitePosDTO.getUsers());
        //公共属性初始化,这里仅取出号码给实例属性初始化时使用-一定要在场景初始化之后就设置到公共属性中
        this.initSerialNumberCommonAttr(sceneInstId, kitePosDTO);
        ExtOrderInfoCache.getInst().defaultPut(sceneInstId, kitePosDTO);
        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }

    @Override
    @KiteTransactional
    public DataResult<Boolean> initSceneAttrValues(String sceneInstId, String operType, String custId, String staffId,
        KitePosDTO kitePosDTO) {
        StopWatch sw = new StopWatch("变更场景初始化-还原属性值");
        sw.start("变更场景初始化-还原属性值");
        LoginInfo loginInfo = ContextUtil.getLoginInfo();
        String serviceOfferId = this.querySceneInstService.getSceneInst(sceneInstId).getServiceOfferId();
        // 设置子线程共享request
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, Boolean.TRUE);
        Map<String, List<KitePosGoodsDTO>> goodsMap = this.getGoodsInSameThread(kitePosDTO);

        this.commonService.initCommonAttrValues(sceneInstId, serviceOfferId, custId, kitePosDTO, loginInfo);
        this.executeTask(sceneInstId, operType, custId, staffId, goodsMap, kitePosDTO, loginInfo);

        sw.stop();
        // 关闭子线程共享request
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, Boolean.FALSE);
        LOGGER.info(sw.prettyPrint());
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    @SuppressWarnings("rawtypes")
    private void executeTask(String sceneInstId, String operType, String custId, String staffId, Map<String, List<KitePosGoodsDTO>> goodsMap, KitePosDTO kitePosDTO, LoginInfo loginInfo) {
        if (KiteMapUtils.isEmpty(goodsMap)) {
            return;
        }
        String transactionId = KiteTransactionUtils.getTransactionId();
        // 创建一个时间标示，作为当前线程池的标识；
        String taskId = String.valueOf(System.currentTimeMillis());
        // 获取多线程管理类
        MultiThreaExecutorManager mteMgr = MultiThreaExecutorManager.getInstans();
        ExecutorTypeEmun executorType = ExecutorTypeEmun.THREAD_POOL_TYPE_COMM_CACHE;

        int threadNum = goodsMap.keySet().size() > Integer.valueOf(KeyConsts.DEFAULT_THREAD_NUM_DOUBLE)
            ? Integer.valueOf(KeyConsts.DEFAULT_THREAD_NUM_DOUBLE)
            : goodsMap.keySet().size();
        mteMgr.newFixedThreadPool(executorType, taskId, threadNum);
        // 创建执行线程类集合
        Collection<ExecuteTask> executeTasks = new ArrayList<ExecuteTask>();
        // 将这个集合放入管理器中的
        mteMgr.putTask(executorType, taskId, executeTasks);
        try {
            List<KitePosGoodsDTO> goodsList = goodsMap.get("gift");
            if (!KiteListUtils.isEmpty(goodsList)) {
                ExecuteTask giftTask = new GiftOfferInstReloadExecuteTask(executorType, taskId, sceneInstId, custId, staffId, goodsList, loginInfo, transactionId);
                executeTasks.add(giftTask);
            }
            goodsMap.keySet().removeIf(key -> KiteStringUtils.equals(key, "gift"));

            // 创建执行任务类-处理主商品
            List<KitePosGoodsDTO> mainGoodsList = goodsMap.get("main");
            if (!KiteListUtils.isEmpty(mainGoodsList)) {
                for (KitePosGoodsDTO goods : mainGoodsList) {
                    goodsList = Lists.newArrayList(goods);
                    ExecuteTask task = new MainOfferInstReloadExecuteTask(executorType, taskId, sceneInstId, custId, staffId, goodsList, loginInfo, transactionId);
                    executeTasks.add(task);
                }
            }
            goodsMap.keySet().removeIf(key -> KiteStringUtils.equals(key, "main"));

            // 创建执行任务类-处理附加商品
            Iterator<String> it = goodsMap.keySet().iterator();
            while (it.hasNext()) {
                goodsList = goodsMap.get(it.next());
                ExecuteTask task = new OfferInstReloadExecuteTask(executorType, taskId, sceneInstId, custId, staffId, goodsList, loginInfo, transactionId);
                executeTasks.add(task);
            }
            // 处理合同，付费关系的线程类
            List<IInstLoader> loaders = CuccInstLoaderFactory.getInstLoaders();
            for(IInstLoader loader : loaders) {
                ExecuteTask task = new OfferInstRelInfoReloadExecuteTask(executorType, taskId, sceneInstId, operType, custId, staffId, kitePosDTO, loginInfo, loader, transactionId);
                executeTasks.add(task);
            }

            // 启动多线程任务
            List<Future<ExecuteResult>> afutures = mteMgr.invokeAll(executorType, taskId);
            // 获取线程返回的处理结果
            for (Future<ExecuteResult> future : afutures) {
                if (null != future.get()) {
                    future.get();
                }
            }
        }
        catch (Exception e) {
            throw new RuntimeException(e.getCause());
        }
        finally {
            // 执行完后关闭线程
            mteMgr.shutDown(executorType, taskId);
            mteMgr.shutDownNow(executorType, taskId);
        }
    }

    /**
     * 异步还原合同的附件
     * @author zhang.song
     * @date 2021-07-16 16:45
     * @param sceneInstId
     * @param custId
     * @param staffCode
     * @param provinceId
     * @param kitePosDTO
     * @return com.iwhalecloud.bss.kite.client.dto.DataResult<java.lang.Boolean>
     */
    @Override
    @KiteTransactional
    public DataResult<Boolean> initMoreSceneAttrValues(String sceneInstId, String custId, String staffCode, String provinceId, KitePosDTO kitePosDTO) {
        List<KiteOfferInst> offerInsts = Lists.newArrayList();
        offerInsts.addAll(this.querySceneInstService.listMainOfferInsts(sceneInstId));
        offerInsts.addAll(this.querySceneInstService.listGiftOfferInsts(sceneInstId));

        Map<String, List<CustContractRsp>> checkContractMap = new HashMap<>();
        Map<String, QryCustAccountReq> checkAccountMap = new HashMap<>();
        offerInsts.forEach(offerInst -> {
            this.initContractMoreInfo(sceneInstId, offerInst.getOfferInstId(), offerInst.getOfferId(), custId, staffCode, provinceId, checkContractMap, kitePosDTO);
            this.initAccountMoreInfo(sceneInstId, offerInst.getOfferInstId(), offerInst.getOfferId(), custId, staffCode, provinceId, checkAccountMap, kitePosDTO);
        });

        this.initSceneOfferInstService.initSerialNumbers(sceneInstId, null, custId, kitePosDTO, null);
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    private void initContractMoreInfo(String sceneInstId, String offerInstId, String offerId, String custId, String staffCode, String provinceId, Map<String, List<CustContractRsp>> checkMap, KitePosDTO kitePosDTO) {
        List<KiteOfferInstContract> kiteOfferInstContractRelList = querySceneInstService.listOfferInstContracts(custId, offerInstId);
        String cateId = CuccPosServiceUtils.getCateId(sceneInstId, custId);
        for (KiteOfferInstContract offerInstContract : kiteOfferInstContractRelList) {
            if (KiteStringUtils.isEmpty(offerInstContract.getContractNo())) {
                continue;
            }
            List<CustContractRsp> contractInfoList = checkMap.get(offerInstContract.getContractNo());
            if (KiteListUtils.isEmpty(contractInfoList) && !KiteStringUtils.isEmpty(offerInstContract.getContractNo())) {
                contractInfoList = infServiceBus
                    .listContractInfo(kitePosDTO.getCustomer().getCustId(), offerInstContract.getContractNo(),
                        offerInstContract.getContractName(), null, provinceId, 1, 10,cateId);
            }

            if (KiteListUtils.isNotEmpty(contractInfoList)) {
                checkMap.put(offerInstContract.getContractNo(), contractInfoList);

                CustContractRsp custContractRsp = contractInfoList.get(0);
                offerInstContract.setContractUrl(custContractRsp.getAccessoryId());
                if (KiteListUtils.isNotEmpty(custContractRsp.getAccessoryInfo())) {
                    offerInstContract.setAttachmentName(custContractRsp.getAccessoryInfo().get(0).getOriginalName());
                }
                this.operateSceneInstService.deleteOfferInstContract(sceneInstId, offerInstContract.getOfferObjInstRelId());
                this.operateSceneInstService.addOfferInstContract(sceneInstId, offerInstContract, offerInstContract.getOfferInstId(), RelType.OFFER_OBJ_REL_TYPE_190000, ActionType.K, KeyConsts.OFFER_CONTRACT_ROLE, offerId);
            }
        }
    }

    private void initAccountMoreInfo(String sceneInstId, String offerInstId, String offerId, String custId, String staffCode, String provinceId, Map<String, QryCustAccountReq> checkMap, KitePosDTO kitePosDTO) {
        List<KiteOfferInstAcct> kiteOfferInstAcctList = querySceneInstService.listOfferInstAccts(custId, offerInstId);
        for (KiteOfferInstAcct kiteOfferInstAcct : kiteOfferInstAcctList) {
            CuccKiteOfferInstAcct cuccKiteOfferInstAcct = (CuccKiteOfferInstAcct) kiteOfferInstAcct;
            if (KiteStringUtils.isEmpty(cuccKiteOfferInstAcct.getCustName()) || KiteStringUtils.isEmpty(cuccKiteOfferInstAcct.getContractId())
                ||KiteStringUtils.isEmpty(cuccKiteOfferInstAcct.getCbssAccountCode())) {
                KitePosAccountDTO acctDto = kitePosDTO.getAccounts().stream().filter(acct -> KiteStringUtils.equals(acct.getAccountId(), cuccKiteOfferInstAcct.getAcctId())).findAny().orElse(null);
                if (KiteObjectUtils.isEmpty(acctDto)) {
                    continue;
                }
                PageInfo<QryCustAccountReq> qryAccount = localAccountService.listCustAccountInfo("", "",
                    acctDto.getPayMode(), acctDto.getAccountId(), "", "", "", acctDto.getProvinceCode(),
                    acctDto.getEparchyCode(), staffCode, 1, 10);
                if (Objects.nonNull(qryAccount) && KiteListUtils.isNotEmpty(qryAccount.getList())) {
                    QryCustAccountReq accountReq = qryAccount.getList().get(0);
                    //acct.setCustName(accountReq.getCustAccount().getCustName());
                    //acct.setContractId(accountReq.getCustAccount().getContractId());
                    cuccKiteOfferInstAcct.setCbssAccountCode(accountReq.getCustAccount().getCbssAccountCode());
                    // 开户时间
                    if (KiteStringUtils.isEmpty(cuccKiteOfferInstAcct.getOpenDateFormat()) && Objects
                        .nonNull(accountReq.getCustAccount().getOpenDate())) {
                        Long time = accountReq.getCustAccount().getOpenDate().getTime();
                        cuccKiteOfferInstAcct.setOpenDateFormat(DateUtils.formatTime(time));
                    }
                    if (KiteStringUtils.isNotEmpty(accountReq.getCustAccount().getCustName())) {
                        cuccKiteOfferInstAcct.setCustName(accountReq.getCustAccount().getCustName());
                    }
                    if (KiteStringUtils.isNotEmpty(accountReq.getCustAccount().getContractId())) {
                        cuccKiteOfferInstAcct.setContractId(accountReq.getCustAccount().getContractId());
                    }
                }
                operateSceneInstService.addOfferInstAcct(sceneInstId, cuccKiteOfferInstAcct, cuccKiteOfferInstAcct.getOfferInstId(), RelType.OFFER_OBJ_REL_TYPE_170000, cuccKiteOfferInstAcct.getActionType(), KeyConsts.OFFER_ACCOUNT_ROLE, offerId);
            }
        }
    }

    /**
     * 获取可多线程处理的商品实例
     * 根据以下分组的方式组装线程数据
     * [融合]：如 [数字对讲（全国）]
     * [融合，SKU]：如 [数字对讲（全国）, 定制连接（全国）]
     * [融合，SKU，附加商品]：如 [数字对讲（全国）, 定制连接（全国）, 附加商品（全国）]
     * @param kitePosDTO
     */
    private Map<String, List<KitePosGoodsDTO>> getGoodsInSameThread(KitePosDTO kitePosDTO) {
        List<KitePosGoodsDTO> gifts = Lists.newArrayList();
        Map<String, List<KitePosGoodsDTO>> goodsMap = new HashMap<>();
        kitePosDTO.getGoods().forEach(goods -> {
            if (GoodsHelper.isGift(goods.getCode())) {
                gifts.add(goods);
                List<KitePosGoodsDTO> goodsList = goodsMap.get("gift");
                if (goodsList == null) {
                    goodsList = Lists.newArrayList();
                }
                goodsList.add(goods);
                goodsMap.put("gift", goodsList);
            }
            else if (goods.getProducts().stream().anyMatch(prod -> KiteStringUtils.equals("add", prod.getType()))) {
                // 附加商品，key要使用主商品的实例ID
                List<KitePosGoodsDTO> goodsList = goodsMap.get(KiteStringUtils.concatWithNnderline("a", goods.getInstanceId()));
                if (goodsList == null) {
                    goodsList = Lists.newArrayList();
                }
                goodsList.add(goods);
                // 添加主商品
                List<KitePosGoodsDTO> parentGoods = kitePosDTO.getGoods().stream().filter(goods1 -> KiteStringUtils.equals(goods1.getInstanceId(), goods.getParentInstId())).collect(Collectors.toList());
                goodsList.addAll(parentGoods);

                goodsMap.put(KiteStringUtils.concatWithNnderline("a", goods.getInstanceId()), goodsList);
            }
            else  {
                List<KitePosGoodsDTO> goodsList = goodsMap.get("main");
                if (goodsList == null) {
                    goodsList = Lists.newArrayList();
                }
                goodsList.add(goods);
                goodsMap.put("main", goodsList);
            }
        });
        return goodsMap;
    }

    private void initSerialNumberCommonAttr(String sceneInstId, KitePosDTO kitePosDTO) {
        InstType instType = this.querySceneInstService.getSceneInst(sceneInstId).getRootInstType();
        if (Objects.equals(InstType.GIFT_OFFER_INST, instType)) {
            List<KitePosUserDTO> mainUsers = kitePosDTO.getUsers().stream().filter(user -> !KiteStringUtils.equals(user.getUserDiffCode(), "-1")).collect(Collectors.toList());
            if (KiteListUtils.isNotEmpty(mainUsers)) {
                // 只有一个主号码
                String serialNumber = mainUsers.get(0).getSerialNumber();
                commonService.setCommonAttrValue(sceneInstId, "business_number", serialNumber, serialNumber, serialNumber);
            }
        }
        else {
            // 业务变更 业务号码回填
            List<KitePosUserDTO> users = kitePosDTO.getUsers();
            if (!KiteListUtils.isEmpty(users)) {
                commonService
                    .setCommonAttrValue(sceneInstId, "business_number", kitePosDTO.getUsers().get(0).getSerialNumber(),
                        kitePosDTO.getUsers().get(0).getSerialNumber(), kitePosDTO.getUsers().get(0).getSerialNumber());
            }
        }
        if (!KiteObjectUtils.isEmpty(kitePosDTO) && KiteListUtils.isNotEmpty(kitePosDTO.getUsers())) {
            commonService.setCommonAttrValue(sceneInstId, "group_user_name", kitePosDTO.getUsers().get(0).getName(),
                kitePosDTO.getUsers().get(0).getName(), kitePosDTO.getUsers().get(0).getName());
        }
    }

    private String getPromotionOfferId(String catagoryId, List<String> offerIds) {
        String promotionOfferId = null;
        List<GoodsDTO> list = goodsService.queryGoodsListInCategroy(catagoryId, null);
        if (KiteListUtils.isNotEmpty(list)) {
            //如果只有1个，默认使用第一个
            if (list.size() == 1) {
                promotionOfferId = list.get(0).getGoodsSku();
            }
            //如果有多个，每个都查一次确认基础商品在哪个促销下面
            else {
                for (GoodsDTO goodsDTO : list) {
                    List<AttrDTO> attrDTOList = CuccOfferKeyAttrCache.get(goodsDTO.getGoodsSku());
                    /*List<AttrDTO> attrDTOList = goodsService.queryGoodKeyAttrs(goodsDTO.getGoodsSku())
                        .getResultObject();*/
                    if (KiteListUtils.isEmpty(attrDTOList)) {
                        // 设备类有多个，但无关键属性
                        Map<String, Object> goodsInfo = CuccOfferOriginalInfoCache.get(goodsDTO.getGoodsSku());
                        //Map<String, Object> goodsInfo = goodsService.queryGoodsByOfferId(goodsDTO.getGoodsSku());
                        List<Map<String, Object>> saleGoods = KiteMapUtils.getValue(goodsInfo, "saleGoods");
                        if (!KiteListUtils.isEmpty(saleGoods)) {
                            for (Map<String, Object> map : saleGoods) {
                                String goodsSku = KiteMapUtils.getString(map, "goodsSku");
                                for (String o : offerIds) {
                                    if (KiteStringUtils.equals(goodsSku, o)) {
                                        promotionOfferId = goodsDTO.getGoodsSku();
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else {
                        String goodsSkuList = attrDTOList.get(0).getGoodsSku();
                        for (String o : offerIds) {
                            if (goodsSkuList.contains(o)) {
                                promotionOfferId = goodsDTO.getGoodsSku();
                                break;
                            }
                        }
                    }
                }
            }
        }
        return promotionOfferId;
    }

    @Override
    public DataResult<ProdRoleModuleVO> getProdRoleModuleVO(String roleId, String prodId, String prodInstId,
        String templateId, String offerId) {
        return ErrorConsts.SUCCESS.getResult(null);
    }

    @Override
    public DataResult<Map<String, Object>> dealPrintTemplate(String sceneInstId, String serviceOfferId) {
        return ErrorConsts.SUCCESS.getResult(null);
    }

    private String getUpServiceOfferId(List<String> bizTypes, List<KitePosGoodsDTO> goods) {
        if (KiteListUtils.isEmpty(goods)) {
            return "";
        }
        for (KitePosGoodsDTO offerSpec : goods) {
            String categoryId = Optional.ofNullable(OfferCache.get(offerSpec.getCode())).map(Offer::getCateId)
                .orElse("");
            //只查询主产品
            for (String serviceOfferId : bizTypes) {
                if (!GoodsInfoTransfer.isAddRoleOffer(offerSpec.getCode(), categoryId)) {
                    DataResult<List<ServiceOfferVO>> serviceOfferTypeVOList = serviceOfferService.getUpServiceOffers(categoryId, serviceOfferId);
                    if (KiteListUtils.isEmpty(serviceOfferTypeVOList.getResultObject())) {
                        serviceOfferTypeVOList = serviceOfferService.getUpServiceOffers(offerSpec.getCode(), serviceOfferId);
                    }
                    if (Objects.nonNull(serviceOfferTypeVOList) && KiteListUtils.isNotEmpty(serviceOfferTypeVOList.getResultObject())) {
                        List<ServiceOfferVO> serviceOfferTypeList = serviceOfferTypeVOList.getResultObject();
                        ServiceOfferVO serviceOffer = serviceOfferTypeList.get(0);
                        if (KiteStringUtils.isNotEmpty(serviceOffer.getUpServiceOfferId()) && !KiteStringUtils.isEqual(serviceOffer.getUpServiceOfferId(), "-1")) {
                            return serviceOffer.getUpServiceOfferId();
                        }
                    }
                }
            }
        }
        return "";
    }

    @Override
    public DataResult<Boolean> saveOrderSummaryInfo(String orderId, String sceneInstId, KitePosDTO kitePosDTO, JSONObject orderData, Map<String, Object> worksheetData) {
        /*Map<String, Object> orderInfo = orderService.getOrderDetail(orderId);
        KitePosDTO kitePosDTO = JSONObject
            .toJavaObject(JSON.parseObject(JSON.toJSONString(orderInfo)), KitePosDTO.class);*/
        KitePosOrderDTO order = kitePosDTO.getOrder();
        KitePosAcceptStaffDTO accept = kitePosDTO.getAccept();
        if (Objects.nonNull(order) && Objects.nonNull(accept)) {
            String flowNodeId = "";
            if (KiteStringUtils.isNotEmpty(order.getFlowNodeId())) {
                int a = order.getFlowNodeId().indexOf("#");
                if(a > 0) {
                    flowNodeId = order.getFlowNodeId().substring(0, order.getFlowNodeId().indexOf("#"));
                } else {
                    flowNodeId = order.getFlowNodeId().substring(0, order.getFlowNodeId().indexOf("_"));
                }
            }
            // String flowNodeId = order.getFlowNodeId().substring(0, order.getFlowNodeId().indexOf("#"));
            String flowNodeName = order.getFlowNodeName();
            // 订单类型
            String orderType = order.getOrderType();
            String orderTypeName = order.getOrderTypeName();
            // 受理时间
            String acceptDate = order.getOrderDate();
            // 受理部门
            String departmentId = accept.getDepartmentId();
            String departmentName = accept.getDepartmentName();
            // 受理员工
            String staffId = accept.getStaffId();
            String staffName = accept.getName();
            // 订单来源
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10009", "24",
                "运营平台销售模块", "24");
            // 订单环节
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10006", flowNodeId,
                flowNodeName, flowNodeId);
            // 订单编号
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10197", orderId,
                orderId, orderId);
            // 订单类型
            commonSevice.setCommonAttrValue(sceneInstId, "ORD10008", orderType,
                orderTypeName, orderType);
            // 受理时间
            commonSevice.setCommonAttrValue(sceneInstId, "ACCEPT_DATE", acceptDate,
                acceptDate, acceptDate);
            // 受理部门
            commonSevice.setCommonAttrValue(sceneInstId, "ACCEPT_DEPARTMENT", departmentId,
                departmentName, departmentId);
            // 受理员工
            commonSevice.setCommonAttrValue(sceneInstId, "ACCEPT_STAFF", staffId,
                staffName, staffId);

            List<KitePosGoodsDTO> goods = kitePosDTO.getGoods();
            if(KiteListUtils.isNotEmpty(goods)) {
                String offerId = goods.get(0).getCode();
                DcPublic dcPublic = DcPublicCache.get("20210719001", offerId);
                // 是五大双线，且不是落地方产品
                if(dcPublic != null) {
                    // 电路代号
                    List<KitePosProductDTO> products = goods.get(0).getProducts();
                    if(KiteListUtils.isNotEmpty(products)) {
                        List<KitePosAttrDTO> attrs = products.get(0).getAttrs();
                        if(KiteListUtils.isNotEmpty(attrs)) {
                            String circuitCode = attrs.stream().filter(attr -> KiteStringUtils.equalsAny(attr.getCode(),"2_0000144","2_0000191")).findAny().map(KitePosAttrDTO::getValue).orElse(null);
                            if(KiteStringUtils.isNotEmpty(circuitCode)) {
                                commonSevice.setCommonAttrValue(sceneInstId, "CIRCUIT_CODE", circuitCode, circuitCode, circuitCode);
                            }
                        }
                    }

                    // O侧全程报竣时间
                    OrderInfoListReq orderInfoListReq = new OrderInfoListReq();
                    orderInfoListReq.setPage("1");
                    orderInfoListReq.setSize("1");
                    orderInfoListReq.setQueryType("order");
                    OrderInfoReq orderInfoReq = new OrderInfoReq();
                    orderInfoReq.setOrderId(orderId);
                    if(KiteListUtils.isNotEmpty(kitePosDTO.getUsers())) {
                        orderInfoReq.setSerialNumber(kitePosDTO.getUsers().get(0).getSerialNumber());
                    }
                    orderInfoListReq.setOrder(orderInfoReq);
                    OrderListInfo orderListInfo = orderService.queryOrderList(orderInfoListReq);
                    if(KiteStringUtils.isEqual(orderListInfo.getCode(), "00000")) {
                        List<OrderInfo> orderInfoList = orderListInfo.getOrderInfoList();
                        if(KiteListUtils.isNotEmpty(orderInfoList)) {
                            String ossCompleteDate = orderInfoList.get(0).getOssCompleteDate();
                            if(KiteStringUtils.isNotEmpty(ossCompleteDate)) {
                                commonSevice.setCommonAttrValue(sceneInstId, "OSS_COMPLETE_DATE", ossCompleteDate, ossCompleteDate, ossCompleteDate);
                                // 起租时间 默认为 O侧的全程报竣时间
                                commonSevice.setCommonAttrValue(sceneInstId, "REC_10057", ossCompleteDate, ossCompleteDate, null);
                            }
                        }
                    }
                }
            }

            List<KitePosAttrDTO> orderAttrList = order.getAttrs();
            if (KiteListUtils.isNotEmpty(orderAttrList)) {
                orderAttrList.forEach(orderAttr -> {
                    if (KiteStringUtils.equals(orderAttr.getCode(), LocalKeyConsts.WHOLE_PROCESS_TIME)) {
                        commonSevice.setCommonAttrValue(sceneInstId, LocalKeyConsts.WHOLE_PROCESS_TIME, orderAttr.getValue(), orderAttr.getValue(), orderAttr.getValue());
                    }
                });
            }
        }

        /**
         * 审核任务名称：originTaskName
         * 处理时间：dealDate
         * 审核不通过原因：failReason
         * 处理人：REC_80005
         * 退单类型：REC_100079
         * 退单范围：REC_100080
         */
        if(KiteStringUtils.isNotEmpty(KiteMapUtils.getString(worksheetData, "orderData"))){
            JSONObject orderDataObj = JSONObject.parseObject(KiteMapUtils.getString(worksheetData, "orderData"));
            if(orderDataObj.containsKey("exceptionInfo")){
                JSONObject expJson = orderDataObj.getJSONObject("exceptionInfo");
                if(Objects.nonNull(expJson)){
                    Map exceptionInfo = JSONObject.toJavaObject(expJson, Map.class);
                    String originTaskName = KiteMapUtils.getString(exceptionInfo, "originTaskName");
                    String dealDate = KiteMapUtils.getString(exceptionInfo, "dealDate");
                    String failReason = KiteMapUtils.getString(exceptionInfo, "failReason");
                    commonSevice.setCommonAttrValue(sceneInstId, "originTaskName", originTaskName, originTaskName, originTaskName);
                    commonSevice.setCommonAttrValue(sceneInstId, "dealDate", dealDate, dealDate, dealDate);
                    commonSevice.setCommonAttrValue(sceneInstId, "failReason", failReason, failReason, failReason);
                }
            }
        }
        if(Objects.nonNull(orderData) && orderData.containsKey("flowData")){
            JSONArray flowData = orderData.getJSONArray("flowData");
            if(Objects.nonNull(flowData)&&flowData.size()>0){
                JSONArray flowValue = flowData.getJSONObject(0).getJSONArray("flowValue");
                List<String> fieldNames = new ArrayList<>(Arrays.asList("REC_80005", "REC_100079", "REC_100080"));
                for (int i = 0; i < flowValue.size(); i++) {
                    JSONObject jsonObject = flowValue.getJSONObject(i);
                    String code = jsonObject.getString("code");
                    if (KiteStringUtils.equalsAny(code, "REC_80005", "REC_100079", "REC_100080")) {
                        String value = jsonObject.getString("value");
                        commonSevice.setCommonAttrValue(sceneInstId, code, value, value, value);
                        fieldNames.remove(code);
                    }
                }
            }
        }
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    private void replaceFinishTime(String sceneInstId) {
        List<KiteProdInst> prodInsts = querySceneInstService.listProdInsts(sceneInstId);
        if (KiteListUtils.isNotEmpty(prodInsts)) {
            prodInsts.forEach(prodInst -> {
                List<KiteAttr> prodInstAttrList = prodInst.listAttrs().stream().filter(instAttr -> ("2_0000122".equals(instAttr.getFieldName()) ||
                    "2_0000123".equals(instAttr.getFieldName()))).collect(Collectors.toList());
                if (KiteListUtils.isNotEmpty(prodInstAttrList)) {
                    prodInstAttrList.forEach(prodInstAttr -> {
                        if ("2_0000122".equals(prodInstAttr.getFieldName())) {
                            commonService.setCommonAttrValue(sceneInstId, LocalKeyConsts.REPLACE_A, prodInstAttr.getValue(), prodInstAttr.getValueDesc(), prodInstAttr.getOriginValue());
                        }
                        if ("2_0000123".equals(prodInstAttr.getFieldName())) {
                            commonService.setCommonAttrValue(sceneInstId, LocalKeyConsts.REPLACE_Z, prodInstAttr.getValue(), prodInstAttr.getValueDesc(), prodInstAttr.getOriginValue());
                        }
                    });
                }
            });
        }
    }

    @Override
    public DataResult<Map<String, Object>> getAllChangeOriginOrder(boolean hasMember, List<QryGrpMemberDTO> memSerialNumbers, String productId,String custId, String serialNumber, String provinceId, String lanId, String staffCode, String userId) {
        StopWatch sw = new StopWatch("变更场景初始化-获取全部变更单");
        // 如果是融合要拼接成员
        List<QryGrpMemberDTO> member = Optional.ofNullable(memSerialNumbers).orElse(Lists.newArrayList());
        UserCenterClient userCenterClient = SpringUtil.getBean(UserCenterClient.class);
        QryGrpMemberListByGrpReq qryGrpMemberListByGrpReq = new QryGrpMemberListByGrpReq();
        qryGrpMemberListByGrpReq.setPrimarySerialNumber(serialNumber);
        int curPage = 0;
        final int pageSize = 10;
        qryGrpMemberListByGrpReq.setPageSize(pageSize);
   /*     sw.start("变更场景初始化-获取全部变更单-获取成员号码列表");
        while (true && hasMember && KiteListUtils.isEmpty(memSerialNumbers)) {
            qryGrpMemberListByGrpReq.setCurPage(++curPage);
            PageInfo<QryGrpMemberDTO> qryGrpMemberDTOPageInfo = userCenterClient
                .qryGrpMemberListByGrp(qryGrpMemberListByGrpReq);
            List<QryGrpMemberDTO> memberDTOList = qryGrpMemberDTOPageInfo.getList();
            if (KiteListUtils.isEmpty(memberDTOList)) {
                break;
            }
            member.addAll(memberDTOList);
            if (memberDTOList.size() < pageSize) {
                break;
            }
        }
        sw.stop();*/
        // 虚拟用户号码本身
        QryGrpMemberDTO grpSelf = new QryGrpMemberDTO();
        grpSelf.setMemCustId(custId);
        grpSelf.setMemGoodsId(productId);
        grpSelf.setMemSerialNumber(serialNumber);
        grpSelf.setMemUserId(userId);
        member.add(0, grpSelf);

        KitePosDTO kitePosDTO = new KitePosDTO();
        Map<String, Object> resultMap = new HashMap<>();

        CompletionService<Map<String,Object>> service = MenuLoadingRuleCompletionService.INSTANCE.getExecutorCompletionService();
        List<Future<Map<String,Object>>> futureList = new ArrayList<>();
        try {
            sw.start("变更场景初始化-获取全部变更单-获取成员变更信息");
           /* for(QryGrpMemberDTO qryGrpMemberDTO : member){
                GetMemberUserInfoTask callTask = new GetMemberUserInfoTask(provinceId, lanId, staffCode, qryGrpMemberDTO);
                Future<Map<String,Object>> future = service.submit(callTask);
                futureList.add(future);
            }
            List<KitePosDTO> memKitePosDTOs = Lists.newArrayList();
            for(Future<Map<String,Object>> future : futureList) {
                Map<String, Object> returnMap = future.get();
                KitePosDTO memKitePosDTO = (KitePosDTO) returnMap.get("memKitePosDTO");
                // 主号处理
                if (memKitePosDTO.getUsers().stream().anyMatch(user -> KiteStringUtils.equals(user.getSerialNumber(), serialNumber))) {
                    resultMap.put("orderId", KiteMapUtils.getString(returnMap, "orderId"));
                    KiteBeanUtils.copyProperties(memKitePosDTO, kitePosDTO);
                }
                else {
                    memKitePosDTOs.add(memKitePosDTO);
                }
            }*/
            List<KitePosDTO> memKitePosDTOs = Lists.newArrayList();
            if(hasMember){
                GetMemberUserInfoTaskRh callTask = new GetMemberUserInfoTaskRh(provinceId, lanId, staffCode, serialNumber, userId);
                Future<Map<String,Object>> future = service.submit(callTask);
                futureList.add(future);
            }else {
                for(QryGrpMemberDTO qryGrpMemberDTO : member){
                    GetMemberUserInfoTask callTask = new GetMemberUserInfoTask(provinceId, lanId, staffCode, qryGrpMemberDTO);
                    Future<Map<String,Object>> future = service.submit(callTask);
                    futureList.add(future);
                }
            }


            for(Future<Map<String,Object>> future : futureList) {
                Map<String, Object> returnMap = future.get();
                KitePosDTO memKitePosDTO = (KitePosDTO) returnMap.get("memKitePosDTO");
                // 主号处理
                if (memKitePosDTO.getUsers().stream().anyMatch(user -> KiteStringUtils.equals(user.getSerialNumber(), serialNumber))) {
                    resultMap.put("orderId", KiteMapUtils.getString(returnMap, "orderId"));
                    KiteBeanUtils.copyProperties(memKitePosDTO, kitePosDTO);
                } /*else {
                    memKitePosDTOs.add(memKitePosDTO);
                }*/
                if(hasMember){
                    List<Map> memKitePosListDTO = (List) returnMap.get("memKitePosListDTO");
                    for(Map mempos:memKitePosListDTO){
                        KitePosDTO memPos = JSONObject
                            .toJavaObject(JSON.parseObject(JSON.toJSONString(mempos)), KitePosDTO.class);
                        memKitePosDTOs.add(memPos);
                    }
                }
            }
            sw.stop();
            // 成员号码处理
            for(KitePosDTO memKitePosDTO : memKitePosDTOs) {
                if (KiteListUtils.isNotEmpty(memKitePosDTO.getGoods())) {
                    List<KitePosGoodsDTO> rootGoods = kitePosDTO.getGoods();
                    if (Objects.isNull(rootGoods)) {
                        kitePosDTO.setGoods(new ArrayList<>());
                        rootGoods = kitePosDTO.getGoods();
                    }
                    rootGoods.addAll(memKitePosDTO.getGoods());
                }

                if (KiteListUtils.isNotEmpty(memKitePosDTO.getUsers())) {
                    List<KitePosUserDTO> rootUsers = kitePosDTO.getUsers();
                    if (Objects.isNull(rootUsers)) {
                        kitePosDTO.setUsers(new ArrayList<>());
                        rootUsers = kitePosDTO.getUsers();
                    }
                    rootUsers.addAll(memKitePosDTO.getUsers());
                }

                if (KiteListUtils.isNotEmpty(memKitePosDTO.getDelivery())) {
                    List<KitePosDeliveryDTO> rootDelivery = kitePosDTO.getDelivery();
                    if (Objects.isNull(rootDelivery)) {
                        kitePosDTO.setDelivery(new ArrayList<>());
                        rootDelivery = kitePosDTO.getDelivery();
                    }
                    rootDelivery.addAll(memKitePosDTO.getDelivery());
                }

                if (KiteListUtils.isNotEmpty(memKitePosDTO.getContract())) {
                    List<KitePosContractDTO> contract = kitePosDTO.getContract();
                    if (Objects.isNull(contract)) {
                        kitePosDTO.setContract(new ArrayList<>());
                        contract = kitePosDTO.getContract();
                    }
                    contract.addAll(memKitePosDTO.getContract());
                }

                if (KiteListUtils.isNotEmpty(memKitePosDTO.getDiscount())) {
                    List<KitePosDiscountDTO> discount = kitePosDTO.getDiscount();
                    if (Objects.isNull(discount)) {
                        kitePosDTO.setDiscount(new ArrayList<>());
                        discount = kitePosDTO.getDiscount();
                    }
                    discount.addAll(memKitePosDTO.getDiscount());
                }

                if (KiteListUtils.isNotEmpty(memKitePosDTO.getAccounts())) {
                    List<KitePosAccountDTO> accounts = kitePosDTO.getAccounts();
                    if (Objects.isNull(accounts)) {
                        kitePosDTO.setAccounts(new ArrayList<>());
                        accounts = kitePosDTO.getAccounts();
                    }
                    accounts.addAll(memKitePosDTO.getAccounts());
                }
            }
            resultMap.put("kitePosDTO", kitePosDTO);
        }
        catch(Exception e) {
//            e.printStackTrace();
            BssException.throwOut("", "", e.getMessage());
        }
        LOGGER.info(sw.prettyPrint());
        return ErrorConsts.SUCCESS.getResult(resultMap);
    }

    @Override
    @KiteTransactional
    public DataResult<Map<String, Object>> initUserIdFromUserCenter(String sceneInstId, CuccContextCustDTO custDTO) {
        List<InstType> instTypes = Lists.newArrayList();
        instTypes.add(InstType.GIFT_OFFER_INST);
        instTypes.add(InstType.MAIN_OFFER_INST);
        List<KiteInst> offerInsts = this.querySceneInstService.listInsts(sceneInstId, instTypes);
        offerInsts.forEach(inst -> {
            String offerId = inst.getSpecId();
            String cateId = OfferCache.get(offerId).getCateId();

            List<KiteProdInst> prodInsts = this.querySceneInstService.listProdInstsFromOfferInst(custDTO.getCustId(), inst.getInstId());

            Optional.ofNullable(prodInsts).orElse(Lists.newArrayList()).stream().filter(prodInst -> (!GoodsInfoTransfer.isAddRoleOffer(offerId, cateId)
                && !LocalKeyConsts.PROD_USE_TYPE_2000.equals(ProductCache.get(prodInst.getSpecId()).getProdUseType()))).forEach(prodInst -> {
                    KiteAttr kiteAttr = new KiteAttr();
                    kiteAttr.setFieldName("userInstId");
                    kiteAttr.setValue(this.getUserId(sceneInstId, custDTO));
                    kiteAttr.setShowType(KeyConsts.PROD_ATTR_SHOW_TYPE_E);
                    kiteAttr.setOrderId("999");
                    prodInst.setAttr(kiteAttr);
                    this.operateSceneInstService.addInst(sceneInstId, prodInst);
                });
        });
        return null;
    }

    private String getUserId(String sceneInstId, CuccContextCustDTO custDTO) {
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "USER_ID");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        return LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, custDTO);
    }

    @Override
    @KiteTransactional
    public DataResult<Boolean> initAttrGroupInstIdFromUserCenter(String sceneInstId, String custId, CuccContextCustDTO custDTO) {
        List<InstType> instTypes = Lists.newArrayList();
        instTypes.add(InstType.PROD_INST);
        List<KiteInst> prodInsts = this.querySceneInstService.listInsts(sceneInstId, instTypes);
        prodInsts.forEach(prodInst -> {
            prodInst.listAttrs().stream().filter(attr -> !KiteStringUtils.isEmpty(attr.getGroupId())).map(KiteAttr::getGroupId).distinct().collect(Collectors.toList()).forEach(groupId -> {
                KiteAttr kiteAttr = new KiteAttr();
                kiteAttr.setFieldName(LocalKeyConsts.PREFIX_ATTR_GROUP_INST_ID + groupId);
                kiteAttr.setValue(this.getAttrGroupInstId(sceneInstId, prodInst.getInstId(), custDTO));
                kiteAttr.setShowType(KeyConsts.PROD_ATTR_SHOW_TYPE_E);
                prodInst.setAttr(kiteAttr);
                this.operateSceneInstService.addInst(sceneInstId, prodInst);
            });
        });
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    private String getAttrGroupInstId(String sceneInstId, String prodInstId, CuccContextCustDTO custDTO) {
        // 生成新的属性组实例ID
        Map<String, String> inParam = new HashMap<>();
        inParam.put("SEQ_TYPE", "SERVICE_ATTR_GROUP_ITEM_ID");
        inParam.put("SYS_TYPE", "1");
        inParam.put("SYS_SOURCE", "");
        return LocalQuerySeqHelper.getSeqBySeqType(inParam, sceneInstId, prodInstId, custDTO);
    }

    /**
     * 设置销售商品ID和名称
     * @param sceneInstId
     * @param spuId
     */
    @Override
    @KiteTransactional
    public DataResult<Boolean> initParentOfferInfo(String sceneInstId, String custId, String spuId) {
        List<KiteOfferInst> offerInsts = Lists.newArrayList();
        offerInsts.addAll(this.querySceneInstService.listMainOfferInsts(sceneInstId));
        offerInsts.addAll(this.querySceneInstService.listGiftOfferInsts(sceneInstId));
        offerInsts.forEach(offerInst -> {
            if (!GoodsInfoTransfer.isAddRoleOffer(offerInst.getSpecId(), OfferCache.get(offerInst.getSpecId()).getCateId())) {
                CuccPosServiceUtils.setExtParamValue(offerInst, sceneInstId, "saleGoodsCode", spuId);
                CuccPosServiceUtils.setExtParamValue(offerInst, sceneInstId, "saleGoodsName", OfferCache.get(spuId).getOfferName());
                this.operateSceneInstService.addInst(sceneInstId, offerInst);
            }
            else {
                // 附加商品，saleGoodsCode和saleGoodsName设置为主商品的编码和名称
                List<KiteInstRelDTO> offerInstRels = querySceneInstService
                    .listInstRelsByZInst(custId, InstType.MAIN_OFFER_INST, offerInst.getOfferInstId(),
                        InstType.MAIN_OFFER_INST);
                if (KiteListUtils.isEmpty(offerInstRels)) {
                    offerInstRels.forEach(offerInstRel -> {
                        KiteOfferInst offerInstt = this.querySceneInstService.getOfferInst(custId, offerInstRel.getaInstId());
                        CuccPosServiceUtils.setExtParamValue(offerInst, sceneInstId, "saleGoodsCode", offerInstt.getSpecId());
                        CuccPosServiceUtils.setExtParamValue(offerInst, sceneInstId, "saleGoodsName", OfferCache.get(offerInstt.getSpecId()).getOfferName());
                        this.operateSceneInstService.addInst(sceneInstId, offerInst);
                    });
                }
            }
        });
        return ErrorConsts.SUCCESS.getResult(Boolean.TRUE);
    }

    @Override
    public DataResult<List<QryGrpMemberDTO>> queryMemberSerialNumbers(String offerId, String serialNumber) {
        List<QryGrpMemberDTO> member = new ArrayList<>();
        if (!KiteStringUtils.equals(OfferCache.get(offerId).getOfferType(), KeyConsts.OFFER_TYPE_15)) {
            return ErrorConsts.SUCCESS.getResult(member);
        }

        UserCenterClient userCenterClient = SpringUtil.getBean(UserCenterClient.class);
        QryGrpMemberListByGrpReq qryGrpMemberListByGrpReq = new QryGrpMemberListByGrpReq();
        qryGrpMemberListByGrpReq.setPrimarySerialNumber(serialNumber);
        int curPage = 0;
        final int pageSize = 10;
        qryGrpMemberListByGrpReq.setPageSize(pageSize);
        while (true) {
            qryGrpMemberListByGrpReq.setCurPage(++curPage);
            PageInfo<QryGrpMemberDTO> qryGrpMemberDTOPageInfo = userCenterClient
                .qryGrpMemberListByGrp(qryGrpMemberListByGrpReq);
            List<QryGrpMemberDTO> memberDTOList = qryGrpMemberDTOPageInfo.getList();
            if (KiteListUtils.isEmpty(memberDTOList)) {
                break;
            }
            member.addAll(memberDTOList);
            if (memberDTOList.size() < pageSize) {
                break;
            }
        }
        return ErrorConsts.SUCCESS.getResult(member);
    }

    /**
     * 五大双线落地方产品，订购初始化，部分属性取值自原单，查询原单详情赋值
     * @author zhang.song
     * @date 2021-07-19 18:37
     * @param sceneInstId
     * @param offerVO
     * @return void
     */
    private void initPlaceProductAttr(String sceneInstId, CuccOfferInitVO offerVO) {
        String orderId = offerVO.getOriginalOrderId();
        if(KiteStringUtils.isEmpty(orderId)) {
            return;
        }

        List<DcPublic> list = DcPublicCache.get("20210719001");
        // 是否五大双线落地方产品
        boolean flag = (list != null) && list.stream().anyMatch(dcPublic -> KiteStringUtils.isEqual(offerVO.getOfferId(), dcPublic.getCodea()));
        if(!flag) {
            return;
        }

        // 类型（1：落地方产品；2：收费方产品）
        String type = list.stream().filter(dcPublic -> KiteStringUtils.isEqual(offerVO.getOfferId(), dcPublic.getCodea())).findAny().map(DcPublic::getCodec).orElse(null);

        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("renderOrderType", "orderFallPlace");
        sceneExtParams.put("fallPlaceOrderId", orderId);
        sceneExtParams.put("fallPlaceFlowId", offerVO.getFlowId());

        // 业务号码
        String serialNumber = null;
        // 用户归属地第二级-地市（发起方地市）
        String cityCode = null;
        // 发起方用户标识
        String userId = null;
        InfServContextDTO context = InfServParamUtils.genGetWorkOrder(orderId, offerVO.getFlowId(), null, null);
        Map<String, Object> workOrderInfo = InfServRouteFactory.getInstance().getWorkOrderInfo(context);
        Map<String, Object> orderDetailMap = MapUtils.getMap(workOrderInfo, "orderData");
        Map<String, Object> worksheetData = MapUtils.getMap(workOrderInfo, "worksheetData");
        sceneExtParams.put("fallPlaceTaskId", MapUtils.getString(worksheetData, "taskId"));
        sceneExtParams.put("fallPlaceTaskCode", MapUtils.getString(worksheetData, "taskCode"));
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);

        List<Map<String, Object>> users = CommonUtil.getList(orderDetailMap, "users");
        if(KiteListUtils.isNotEmpty(users)) {
            Map<String, Object> user = users.get(0);
            serialNumber = KiteMapUtils.getString(user, "serialNumber");
            userId = KiteMapUtils.getString(user, "userId");
            cityCode = KiteMapUtils.getString(user, "cityCode");

            // 若地市为空，判断区县是否存在，存在，根绝区县查地市
            if(KiteStringUtils.isEmpty(cityCode)) {
                String districtCode = KiteMapUtils.getString(user, "districtCode");
                UnicomRegion unicomRegion = unicomRegionService.getRegion(districtCode);
                if(unicomRegion != null) {
                    cityCode = unicomRegion.getParRegionCode();
                }
            }
        }

        // 一站式业务信息ID
        String serviceId = null;
        String cityA = null;
        String cityZ = null;
        String ordScope = null;
        String peNet = null;

        List<Map<String, Object>> goods = CommonUtil.getList(orderDetailMap, "goods");
        if(KiteListUtils.isNotEmpty(goods)) {
            List<Map<String, Object>> products = CommonUtil.getList(goods.get(0), "products");
            if(KiteListUtils.isNotEmpty(products)) {
                List<Map<String, Object>> attrs = CommonUtil.getList(products.get(0), "attrs");
                if(KiteListUtils.isNotEmpty(attrs)) {
                    // 一站式业务信息ID、A/Z端省市区的属性编码、（MPLS-VPN关键属性）电路租用范围、PE归属网络
                    String[] fieldNames = new String[]{"2_0000099","2_0000220","2_0000221","2_0000222","2_0000107","2_0000109","2_0000111","2_0000004","2_0000048"};
                    Map<String, String> attrMap = new HashMap<>();
                    attrs.forEach(temp -> {
                        if(KiteStringUtils.equalsAny(KiteMapUtils.getString(temp, "code"), fieldNames)) {
                            attrMap.put(KiteMapUtils.getString(temp, "code"), KiteMapUtils.getString(temp, "value"));
                        }
                    });

                    serviceId = KiteMapUtils.getString(attrMap, "2_0000099");
                    ordScope = KiteMapUtils.getString(attrMap, "2_0000004");
                    peNet = KiteMapUtils.getString(attrMap, "2_0000048");
                    // 城市A/Z 取原单装机地址第二级-地市
                    cityA = KiteMapUtils.getString(attrMap, "2_0000221");
                    cityZ = KiteMapUtils.getString(attrMap, "2_0000109");
                }
            }
        }

        List<KiteProdInst> kiteProdInstList = querySceneInstService.listProdInsts(sceneInstId);
        for (KiteProdInst kiteProdInst : kiteProdInstList) {
            // 发起方地市（取原单用户归属地地市编码）
            KiteAttr kiteAttr1 = kiteProdInst.getAttr("200002058");
            if(Objects.nonNull(kiteAttr1)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr1.getFieldName(), cityCode, sceneInstId, null);
            }
            // 发起地市业务号码
            KiteAttr kiteAttr2 = kiteProdInst.getAttr("200002059");
            if(Objects.nonNull(kiteAttr2)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr2.getFieldName(), serialNumber, sceneInstId, null);
            }
            // 一站式业务信息ID
            KiteAttr kiteAttr3 = kiteProdInst.getAttr("2_0000099");
            if(Objects.nonNull(kiteAttr3)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr3.getFieldName(), serviceId, sceneInstId, null);
            }
            // 城市(A端)
            KiteAttr kiteAttr4 = getAnyAttr(kiteProdInst, "2_0000104","2_0000209","210005122");
            if(Objects.nonNull(kiteAttr4)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr4.getFieldName(), cityA, sceneInstId, null);
            }
            // 城市(Z端)
            KiteAttr kiteAttr5 = kiteProdInst.getAttr("2_0000105");
            if(Objects.nonNull(kiteAttr5)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr5.getFieldName(), cityZ, sceneInstId, null);
            }
            // 发起方用户标识
            KiteAttr kiteAttr6 = kiteProdInst.getAttr("200002060");
            if(Objects.nonNull(kiteAttr6)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr6.getFieldName(), userId, sceneInstId, null);
            }
            // 电路租用范围
            KiteAttr kiteAttr7 = kiteProdInst.getAttr("2_0000004");
            if(Objects.nonNull(kiteAttr7)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr7.getFieldName(), ordScope, sceneInstId, null);
            }
            // PE归属网络
            KiteAttr kiteAttr8 = kiteProdInst.getAttr("2_0000048");
            if(Objects.nonNull(kiteAttr8)) {
                operateInstAttrService.setAttrValue(kiteProdInst, kiteAttr8.getFieldName(), peNet, sceneInstId, null);
            }
        }

        if(KiteStringUtils.isEqual(type, "1")) {
            // 起租时间
            String startRentDate = null;
            List<Map<String, Object>> flowData = CommonUtil.getList(orderDetailMap, "flowData");
            if(KiteListUtils.isNotEmpty(flowData)) {
                Map<String, Object> startRentFlowMap = flowData.stream().filter(flowMap ->
                    KiteStringUtils.equals(KiteMapUtils.getString(flowMap, "flowKey"), "OrderStartRent")).findFirst().orElse(null);

                String startRentJson = KiteMapUtils.getString(startRentFlowMap, "flowValue");
                if(KiteStringUtils.isJsonArray(startRentJson)) {
                    List<Map> rentInfoList = JSONArray.parseArray(startRentJson, Map.class);
                    if(KiteListUtils.isNotEmpty(rentInfoList)) {
                        Map<String, Object> startRentMap = rentInfoList.stream().filter(rentInfo ->
                            KiteStringUtils.equals(KiteMapUtils.getString(rentInfo, "code"), "REC_10057")).findAny().orElse(null);

                        startRentDate = KiteMapUtils.getString(startRentMap, "value");
                    }
                }
            }
            if(KiteStringUtils.isEmpty(startRentDate)) {
                startRentDate = KiteMapUtils.getString(KiteMapUtils.getMap(orderDetailMap, "order"), "startRentDate");
            }
            if(KiteStringUtils.isNotEmpty(startRentDate)) {
                if(startRentDate.length() > 10) {
                    startRentDate = startRentDate.substring(0, 10);
                }

                // 起租时间，取原单的起租时间
                KiteAttr attr = querySceneInstService.getCommonAttr(sceneInstId, LocalKeyConsts.START_RENT_DATE);
                if(Objects.nonNull(attr)) {
                    attr.setValue(startRentDate);
                    operateSceneInstService.setCommonAttr(sceneInstId, attr);
                }
            }
        }

        if(KiteStringUtils.isEqual(type, "2")) {
            Map<String, Object> order = MapUtils.getMap(orderDetailMap, "order");
            List<Map<String, Object>> orderAttrs = CommonUtil.getList(order, "attrs");
            if(KiteListUtils.isNotEmpty(orderAttrs)) {
                Map<String, Object> orderNatureAttr = orderAttrs.stream().filter(temp -> KiteStringUtils.isEqual(KiteMapUtils.getString(temp, "code"), "ORD10001")).findAny().orElse(null);
                // 订单性质，取原单的起租时间
                String orderNature = MapUtils.getString(orderNatureAttr, "value");
                if(KiteStringUtils.isNotEmpty(orderNature)) {
                    KiteAttr attr = querySceneInstService.getCommonAttr(sceneInstId, LocalKeyConsts.ORDER_NATURE);
                    if(Objects.nonNull(attr)) {
                        attr.setValue(orderNature);
                        operateSceneInstService.setCommonAttr(sceneInstId, attr);
                    }
                }
            }
        }
    }

    private static KiteAttr getAnyAttr(KiteProdInst kiteProdInst, String ...fieldNames) {
        Map<String, KiteAttr> attrMap = kiteProdInst.getAttrMap();
        for (String fieldName : fieldNames) {
            if(attrMap.containsKey(fieldName)) {
                return attrMap.get(fieldName);
            }
        }
        return null;
    }

    @Override
    @KiteTransactional
    public DataResult<String> createResaleScene(ResaleOrderRequest resaleOrderRequest, KitePosDTO userKitePosDTO) {
        StopWatch sw = new StopWatch("返销场景初始化");
        sw.start("返销场景创建");
        String sceneInstId = this.createOfferScene(resaleOrderRequest.getServiceOfferId(), null, LocalKeyConsts.ASK_SOURCE_USER,
            resaleOrderRequest.getCustId(), resaleOrderRequest.getCustName(), resaleOrderRequest.getStaffId(), resaleOrderRequest.getLanId(), resaleOrderRequest.getRegionId(), userKitePosDTO).getResultObject();
        sw.stop();
        LOGGER.info(sw.prettyPrint());
        Map<String, Object> sceneExtParams = this.querySceneInstService.getExtParameter(sceneInstId);
        sceneExtParams.put("serialNumber", userKitePosDTO.getUsers());
        sceneExtParams.put(LocalKeyConsts.BUSI_CHANGE_SCENE, "T");
        sceneExtParams.put(LocalKeyConsts.BUSI_CHANGE_SCENE_ONE, "T");
        this.operateSceneInstService.setExtParameter(sceneInstId, sceneExtParams);
        this.setSceneInstId(sceneInstId, resaleOrderRequest.getServiceOfferId(), resaleOrderRequest.getCartId(), resaleOrderRequest.getCustId(), "1008");
        return ErrorConsts.SUCCESS.getResult(sceneInstId);
    }
}
